diff --git a/src/System.Linq.Queryable/System.Linq.Queryable.sln b/src/System.Linq.Queryable/System.Linq.Queryable.sln
new file mode 100644
index 000000000000..2891d7228ae1
--- /dev/null
+++ b/src/System.Linq.Queryable/System.Linq.Queryable.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Linq.Queryable", "src\System.Linq.Queryable.csproj", "{BE12B753-C130-4B68-86E3-877F1AEE52C0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Linq.Queryable.Tests", "tests\System.Linq.Queryable.Tests.csproj", "{7B88D79B-B799-4116-A7D0-AED572540CD4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BE12B753-C130-4B68-86E3-877F1AEE52C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE12B753-C130-4B68-86E3-877F1AEE52C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE12B753-C130-4B68-86E3-877F1AEE52C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE12B753-C130-4B68-86E3-877F1AEE52C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B88D79B-B799-4116-A7D0-AED572540CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B88D79B-B799-4116-A7D0-AED572540CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B88D79B-B799-4116-A7D0-AED572540CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B88D79B-B799-4116-A7D0-AED572540CD4}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/System.Linq.Queryable/src/Resources/SR.cs b/src/System.Linq.Queryable/src/Resources/SR.cs
new file mode 100644
index 000000000000..a51979ed3911
--- /dev/null
+++ b/src/System.Linq.Queryable/src/Resources/SR.cs
@@ -0,0 +1,51 @@
+// Do not edit this file manually it is auto-generated during the build based on the .resx file for this project.
+namespace System
+{
+ internal static partial class SR
+ {
+#pragma warning disable 0414
+ private const string s_resourcesName = "System.Linq.Queryable.resources"; // assembly Name + .resources
+#pragma warning restore 0414
+
+#if !DEBUGRESOURCES
+ internal static string ArgumentNotIEnumerableGeneric {
+ get { return SR.GetResourceString("ArgumentNotIEnumerableGeneric", null); }
+ }
+ internal static string UnhandledExpressionType {
+ get { return SR.GetResourceString("UnhandledExpressionType", null); }
+ }
+ internal static string UnhandledBindingType {
+ get { return SR.GetResourceString("UnhandledBindingType", null); }
+ }
+ internal static string ArgumentNotValid {
+ get { return SR.GetResourceString("ArgumentNotValid", null); }
+ }
+ internal static string NoMethodOnType {
+ get { return SR.GetResourceString("NoMethodOnType", null); }
+ }
+ internal static string NoMethodOnTypeMatchingArguments {
+ get { return SR.GetResourceString("NoMethodOnTypeMatchingArguments", null); }
+ }
+#else
+ internal static string ArgumentNotIEnumerableGeneric {
+ get { return SR.GetResourceString("ArgumentNotIEnumerableGeneric", @"{0} is not IEnumerable<>"); }
+ }
+ internal static string UnhandledExpressionType {
+ get { return SR.GetResourceString("UnhandledExpressionType", @"Unhandled Expression Type: {0}"); }
+ }
+ internal static string UnhandledBindingType {
+ get { return SR.GetResourceString("UnhandledBindingType", @"Unhandled Binding Type: {0}"); }
+ }
+ internal static string ArgumentNotValid {
+ get { return SR.GetResourceString("ArgumentNotValid", @"Argument {0} is not valid"); }
+ }
+ internal static string NoMethodOnType {
+ get { return SR.GetResourceString("NoMethodOnType", @"There is no method '{0}' on type '{1}'"); }
+ }
+ internal static string NoMethodOnTypeMatchingArguments {
+ get { return SR.GetResourceString("NoMethodOnTypeMatchingArguments", @"There is no method '{0}' on type '{1}' that matches the specified arguments"); }
+ }
+
+#endif
+ }
+}
diff --git a/src/System.Linq.Queryable/src/Resources/Strings.resx b/src/System.Linq.Queryable/src/Resources/Strings.resx
new file mode 100644
index 000000000000..1a9854307ffb
--- /dev/null
+++ b/src/System.Linq.Queryable/src/Resources/Strings.resx
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ {0} is not IEnumerable<>
+
+
+ Unhandled Expression Type: {0}
+
+
+ Unhandled Binding Type: {0}
+
+
+ Argument {0} is not valid
+
+
+ There is no method '{0}' on type '{1}'
+
+
+ There is no method '{0}' on type '{1}' that matches the specified arguments
+
+
\ No newline at end of file
diff --git a/src/System.Linq.Queryable/src/System.Linq.Queryable.csproj b/src/System.Linq.Queryable/src/System.Linq.Queryable.csproj
new file mode 100644
index 000000000000..a2d7d1ca9c1f
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System.Linq.Queryable.csproj
@@ -0,0 +1,35 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {BE12B753-C130-4B68-86E3-877F1AEE52C0}
+ Library
+ System.Linq.Queryable
+ System.Linq.Queryable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs b/src/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs
new file mode 100644
index 000000000000..bcc84911b7be
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/EnumerableExecutor.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace System.Linq
+{
+ // Must remain public for Silverlight
+ public abstract class EnumerableExecutor
+ {
+ internal abstract object ExecuteBoxed();
+
+ internal static EnumerableExecutor Create(Expression expression)
+ {
+ Type execType = typeof(EnumerableExecutor<>).MakeGenericType(expression.Type);
+ return (EnumerableExecutor)Activator.CreateInstance(execType, new object[] { expression });
+ }
+ }
+
+ // Must remain public for Silverlight
+ public class EnumerableExecutor : EnumerableExecutor
+ {
+ private Expression _expression;
+ private Func _func;
+
+ // Must remain public for Silverlight
+ public EnumerableExecutor(Expression expression)
+ {
+ _expression = expression;
+ }
+
+ internal override object ExecuteBoxed()
+ {
+ return this.Execute();
+ }
+
+ internal T Execute()
+ {
+ if (_func == null)
+ {
+ EnumerableRewriter rewriter = new EnumerableRewriter();
+ Expression body = rewriter.Visit(_expression);
+ Expression> f = Expression.Lambda>(body, (IEnumerable)null);
+ _func = f.Compile();
+ }
+ return _func();
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs b/src/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs
new file mode 100644
index 000000000000..efbc7c6c991a
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/EnumerableQuery.cs
@@ -0,0 +1,155 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+
+namespace System.Linq
+{
+ // Must remain public for Silverlight
+ public abstract class EnumerableQuery
+ {
+ internal abstract Expression Expression { get; }
+ internal abstract IEnumerable Enumerable { get; }
+ internal static IQueryable Create(Type elementType, IEnumerable sequence)
+ {
+ Type seqType = typeof(EnumerableQuery<>).MakeGenericType(elementType);
+ return (IQueryable)Activator.CreateInstance(seqType, new object[] { sequence });
+ }
+
+ internal static IQueryable Create(Type elementType, Expression expression)
+ {
+ Type seqType = typeof(EnumerableQuery<>).MakeGenericType(elementType);
+ return (IQueryable)Activator.CreateInstance(seqType, new object[] { expression });
+ }
+ }
+
+ // Must remain public for Silverlight
+ public class EnumerableQuery : EnumerableQuery, IOrderedQueryable, IQueryable, IQueryProvider, IEnumerable, IEnumerable
+ {
+ private Expression _expression;
+ private IEnumerable _enumerable;
+
+ IQueryProvider IQueryable.Provider
+ {
+ get
+ {
+ return (IQueryProvider)this;
+ }
+ }
+
+ // Must remain public for Silverlight
+ public EnumerableQuery(IEnumerable enumerable)
+ {
+ _enumerable = enumerable;
+ _expression = Expression.Constant(this);
+ }
+
+ // Must remain public for Silverlight
+ public EnumerableQuery(Expression expression)
+ {
+ _expression = expression;
+ }
+
+ internal override Expression Expression
+ {
+ get { return _expression; }
+ }
+
+ internal override IEnumerable Enumerable
+ {
+ get { return _enumerable; }
+ }
+
+ Expression IQueryable.Expression
+ {
+ get { return _expression; }
+ }
+
+ Type IQueryable.ElementType
+ {
+ get { return typeof(T); }
+ }
+
+ IQueryable IQueryProvider.CreateQuery(Expression expression)
+ {
+ if (expression == null)
+ throw Error.ArgumentNull("expression");
+ Type iqType = TypeHelper.FindGenericType(typeof(IQueryable<>), expression.Type);
+ if (iqType == null)
+ throw Error.ArgumentNotValid("expression");
+ return EnumerableQuery.Create(iqType.GetGenericArguments()[0], expression);
+ }
+
+ IQueryable IQueryProvider.CreateQuery(Expression expression)
+ {
+ if (expression == null)
+ throw Error.ArgumentNull("expression");
+ if (!typeof(IQueryable).IsAssignableFrom(expression.Type))
+ {
+ throw Error.ArgumentNotValid("expression");
+ }
+ return new EnumerableQuery(expression);
+ }
+
+ // Baselining as Safe for Mix demo so that interface can be transparent. Marking this
+ // critical (which was the original annotation when porting to silverlight) would violate
+ // fxcop security rules if the interface isn't also critical. However, transparent code
+ // can't access this anyway for Mix since we're not exposing AsQueryable().
+ //
+ // Note, the above assertion no longer holds. Now making AsQueryable() public again
+ // the security fallout of which will need to be re-examined.
+ object IQueryProvider.Execute(Expression expression)
+ {
+ if (expression == null)
+ throw Error.ArgumentNull("expression");
+ Type execType = typeof(EnumerableExecutor<>).MakeGenericType(expression.Type);
+ return EnumerableExecutor.Create(expression).ExecuteBoxed();
+ }
+
+ // see above
+ S IQueryProvider.Execute(Expression expression)
+ {
+ if (expression == null)
+ throw Error.ArgumentNull("expression");
+ if (!typeof(S).IsAssignableFrom(expression.Type))
+ throw Error.ArgumentNotValid("expression");
+ return new EnumerableExecutor(expression).Execute();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ private IEnumerator GetEnumerator()
+ {
+ if (_enumerable == null)
+ {
+ EnumerableRewriter rewriter = new EnumerableRewriter();
+ Expression body = rewriter.Visit(_expression);
+ Expression>> f = Expression.Lambda>>(body, (IEnumerable)null);
+ _enumerable = f.Compile()();
+ }
+ return _enumerable.GetEnumerator();
+ }
+
+ public override string ToString()
+ {
+ ConstantExpression c = _expression as ConstantExpression;
+ if (c != null && c.Value == this)
+ {
+ if (_enumerable != null)
+ return _enumerable.ToString();
+ return "null";
+ }
+ return _expression.ToString();
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs b/src/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs
new file mode 100644
index 000000000000..4e95dac9e0a3
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/EnumerableRewriter.cs
@@ -0,0 +1,247 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace System.Linq
+{
+ internal class EnumerableRewriter : OldExpressionVisitor
+ {
+ internal EnumerableRewriter()
+ {
+ }
+
+ internal override Expression VisitMethodCall(MethodCallExpression m)
+ {
+ Expression obj = this.Visit(m.Object);
+ ReadOnlyCollection args = this.VisitExpressionList(m.Arguments);
+
+ // check for args changed
+ if (obj != m.Object || args != m.Arguments)
+ {
+ Expression[] argArray = args.ToArray();
+ Type[] typeArgs = (m.Method.IsGenericMethod) ? m.Method.GetGenericArguments() : null;
+
+ if ((m.Method.IsStatic || m.Method.DeclaringType.IsAssignableFrom(obj.Type))
+ && ArgsMatch(m.Method, args, typeArgs))
+ {
+ // current method is still valid
+ return Expression.Call(obj, m.Method, args);
+ }
+ else if (m.Method.DeclaringType == typeof(Queryable))
+ {
+ // convert Queryable method to Enumerable method
+ MethodInfo seqMethod = FindEnumerableMethod(m.Method.Name, args, typeArgs);
+ args = this.FixupQuotedArgs(seqMethod, args);
+ return Expression.Call(obj, seqMethod, args);
+ }
+ else
+ {
+ // rebind to new method
+ MethodInfo method = FindMethod(m.Method.DeclaringType, m.Method.Name, args, typeArgs);
+ args = this.FixupQuotedArgs(method, args);
+ return Expression.Call(obj, method, args);
+ }
+ }
+ return m;
+ }
+
+ private ReadOnlyCollection FixupQuotedArgs(MethodInfo mi, ReadOnlyCollection argList)
+ {
+ ParameterInfo[] pis = mi.GetParameters();
+ if (pis.Length > 0)
+ {
+ List newArgs = null;
+ for (int i = 0, n = pis.Length; i < n; i++)
+ {
+ Expression arg = argList[i];
+ ParameterInfo pi = pis[i];
+ arg = FixupQuotedExpression(pi.ParameterType, arg);
+ if (newArgs == null && arg != argList[i])
+ {
+ newArgs = new List(argList.Count);
+ for (int j = 0; j < i; j++)
+ {
+ newArgs.Add(argList[j]);
+ }
+ }
+ if (newArgs != null)
+ {
+ newArgs.Add(arg);
+ }
+ }
+ if (newArgs != null)
+ argList = newArgs.ToReadOnlyCollection();
+ }
+ return argList;
+ }
+
+ private Expression FixupQuotedExpression(Type type, Expression expression)
+ {
+ Expression expr = expression;
+ while (true)
+ {
+ if (type.IsAssignableFrom(expr.Type))
+ return expr;
+ if (expr.NodeType != ExpressionType.Quote)
+ break;
+ expr = ((UnaryExpression)expr).Operand;
+ }
+ if (!type.IsAssignableFrom(expr.Type) && type.IsArray && expr.NodeType == ExpressionType.NewArrayInit)
+ {
+ Type strippedType = StripExpression(expr.Type);
+ if (type.IsAssignableFrom(strippedType))
+ {
+ Type elementType = type.GetElementType();
+ NewArrayExpression na = (NewArrayExpression)expr;
+ List exprs = new List(na.Expressions.Count);
+ for (int i = 0, n = na.Expressions.Count; i < n; i++)
+ {
+ exprs.Add(this.FixupQuotedExpression(elementType, na.Expressions[i]));
+ }
+ expression = Expression.NewArrayInit(elementType, exprs);
+ }
+ }
+ return expression;
+ }
+
+ internal override Expression VisitLambda(LambdaExpression lambda)
+ {
+ return lambda;
+ }
+
+ private static Type GetPublicType(Type t)
+ {
+ // If we create a constant explicitly typed to be a private nested type,
+ // such as Lookup<,>.Grouping or a compiler-generated iterator class, then
+ // we cannot use the expression tree in a context which has only execution
+ // permissions. We should endeavour to translate constants into
+ // new constants which have public types.
+ if (t.GetTypeInfo().IsGenericType && t.GetTypeInfo().GetGenericTypeDefinition().GetTypeInfo().ImplementedInterfaces.Contains(typeof(IGrouping<,>)))
+ return typeof(IGrouping<,>).MakeGenericType(t.GetGenericArguments());
+ if (!t.GetTypeInfo().IsNestedPrivate)
+ return t;
+ foreach (Type iType in t.GetTypeInfo().ImplementedInterfaces)
+ {
+ if (iType.GetTypeInfo().IsGenericType && iType.GetTypeInfo().GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return iType;
+ }
+ if (typeof(IEnumerable).IsAssignableFrom(t))
+ return typeof(IEnumerable);
+ return t;
+ }
+
+ internal override Expression VisitConstant(ConstantExpression c)
+ {
+ EnumerableQuery sq = c.Value as EnumerableQuery;
+ if (sq != null)
+ {
+ if (sq.Enumerable != null)
+ {
+ Type t = GetPublicType(sq.Enumerable.GetType());
+ return Expression.Constant(sq.Enumerable, t);
+ }
+ return this.Visit(sq.Expression);
+ }
+ return c;
+ }
+
+ internal override Expression VisitParameter(ParameterExpression p)
+ {
+ return p;
+ }
+
+ private static volatile ILookup s_seqMethods;
+ private static MethodInfo FindEnumerableMethod(string name, ReadOnlyCollection args, params Type[] typeArgs)
+ {
+ if (s_seqMethods == null)
+ {
+ s_seqMethods = typeof(Enumerable).GetStaticMethods().ToLookup(m => m.Name);
+ }
+ MethodInfo mi = s_seqMethods[name].FirstOrDefault(m => ArgsMatch(m, args, typeArgs));
+ if (mi == null)
+ throw Error.NoMethodOnTypeMatchingArguments(name, typeof(Enumerable));
+ if (typeArgs != null)
+ return mi.MakeGenericMethod(typeArgs);
+ return mi;
+ }
+
+ internal static MethodInfo FindMethod(Type type, string name, ReadOnlyCollection args, Type[] typeArgs)
+ {
+ MethodInfo[] methods = type.GetStaticMethods().Where(m => m.Name == name).ToArray();
+ if (methods.Length == 0)
+ throw Error.NoMethodOnType(name, type);
+ MethodInfo mi = methods.FirstOrDefault(m => ArgsMatch(m, args, typeArgs));
+ if (mi == null)
+ throw Error.NoMethodOnTypeMatchingArguments(name, type);
+ if (typeArgs != null)
+ return mi.MakeGenericMethod(typeArgs);
+ return mi;
+ }
+
+ private static bool ArgsMatch(MethodInfo m, ReadOnlyCollection args, Type[] typeArgs)
+ {
+ ParameterInfo[] mParams = m.GetParameters();
+ if (mParams.Length != args.Count)
+ return false;
+ if (!m.IsGenericMethod && typeArgs != null && typeArgs.Length > 0)
+ {
+ return false;
+ }
+ if (!m.IsGenericMethodDefinition && m.IsGenericMethod && m.ContainsGenericParameters)
+ {
+ m = m.GetGenericMethodDefinition();
+ }
+ if (m.IsGenericMethodDefinition)
+ {
+ if (typeArgs == null || typeArgs.Length == 0)
+ return false;
+ if (m.GetGenericArguments().Length != typeArgs.Length)
+ return false;
+ m = m.MakeGenericMethod(typeArgs);
+ mParams = m.GetParameters();
+ }
+ for (int i = 0, n = args.Count; i < n; i++)
+ {
+ Type parameterType = mParams[i].ParameterType;
+ if (parameterType == null)
+ return false;
+ if (parameterType.IsByRef)
+ parameterType = parameterType.GetElementType();
+ Expression arg = args[i];
+ if (!parameterType.IsAssignableFrom(arg.Type))
+ {
+ if (arg.NodeType == ExpressionType.Quote)
+ {
+ arg = ((UnaryExpression)arg).Operand;
+ }
+ if (!parameterType.IsAssignableFrom(arg.Type) &&
+ !parameterType.IsAssignableFrom(StripExpression(arg.Type)))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static Type StripExpression(Type type)
+ {
+ bool isArray = type.IsArray;
+ Type tmp = isArray ? type.GetElementType() : type;
+ Type eType = TypeHelper.FindGenericType(typeof(Expression<>), tmp);
+ if (eType != null)
+ tmp = eType.GetGenericArguments()[0];
+ if (isArray)
+ {
+ int rank = type.GetArrayRank();
+ return (rank == 1) ? tmp.MakeArrayType() : tmp.MakeArrayType(rank);
+ }
+ return type;
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/Error.cs b/src/System.Linq.Queryable/src/System/Linq/Error.cs
new file mode 100644
index 000000000000..80f497dfdb85
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/Error.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace System.Linq
+{
+ internal class Error
+ {
+ internal static Exception ArgumentNull(string message)
+ {
+ return new ArgumentNullException(message);
+ }
+
+ internal static Exception ArgumentNotIEnumerableGeneric(string message)
+ {
+ return new ArgumentException(Strings.ArgumentNotIEnumerableGeneric(message));
+ }
+
+ internal static Exception ArgumentNotValid(string message)
+ {
+ return new ArgumentException(Strings.ArgumentNotValid(message));
+ }
+
+ internal static Exception UnhandledExpressionType(object message)
+ {
+ return new ArgumentException(Strings.UnhandledExpressionType(message));
+ }
+
+ internal static Exception UnhandledBindingType(object message)
+ {
+ return new ArgumentException(Strings.UnhandledBindingType(message));
+ }
+
+ internal static Exception ArgumentOutOfRange(string message)
+ {
+ return new ArgumentOutOfRangeException(message);
+ }
+
+ internal static Exception NoMethodOnType(string name, object type)
+ {
+ return new InvalidOperationException(Strings.NoMethodOnType(name, type));
+ }
+
+ internal static Exception NoMethodOnTypeMatchingArguments(string name, object type)
+ {
+ return new InvalidOperationException(Strings.NoMethodOnTypeMatchingArguments(name, type));
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/Expressions/OldExpressionVisitor.cs b/src/System.Linq.Queryable/src/System/Linq/Expressions/OldExpressionVisitor.cs
new file mode 100644
index 000000000000..0f2c70c19a65
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/Expressions/OldExpressionVisitor.cs
@@ -0,0 +1,367 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace System.Linq.Expressions
+{
+ internal abstract class OldExpressionVisitor
+ {
+ internal OldExpressionVisitor()
+ {
+ }
+
+ internal virtual Expression Visit(Expression exp)
+ {
+ if (exp == null)
+ return exp;
+ switch (exp.NodeType)
+ {
+ case ExpressionType.UnaryPlus:
+ case ExpressionType.Negate:
+ case ExpressionType.NegateChecked:
+ case ExpressionType.Not:
+ case ExpressionType.Convert:
+ case ExpressionType.ConvertChecked:
+ case ExpressionType.ArrayLength:
+ case ExpressionType.Quote:
+ case ExpressionType.TypeAs:
+ return this.VisitUnary((UnaryExpression)exp);
+ case ExpressionType.Add:
+ case ExpressionType.AddChecked:
+ case ExpressionType.Subtract:
+ case ExpressionType.SubtractChecked:
+ case ExpressionType.Multiply:
+ case ExpressionType.MultiplyChecked:
+ case ExpressionType.Divide:
+ case ExpressionType.Modulo:
+ case ExpressionType.Power:
+ case ExpressionType.And:
+ case ExpressionType.AndAlso:
+ case ExpressionType.Or:
+ case ExpressionType.OrElse:
+ case ExpressionType.LessThan:
+ case ExpressionType.LessThanOrEqual:
+ case ExpressionType.GreaterThan:
+ case ExpressionType.GreaterThanOrEqual:
+ case ExpressionType.Equal:
+ case ExpressionType.NotEqual:
+ case ExpressionType.Coalesce:
+ case ExpressionType.ArrayIndex:
+ case ExpressionType.RightShift:
+ case ExpressionType.LeftShift:
+ case ExpressionType.ExclusiveOr:
+ return this.VisitBinary((BinaryExpression)exp);
+ case ExpressionType.TypeIs:
+ return this.VisitTypeIs((TypeBinaryExpression)exp);
+ case ExpressionType.Conditional:
+ return this.VisitConditional((ConditionalExpression)exp);
+ case ExpressionType.Constant:
+ return this.VisitConstant((ConstantExpression)exp);
+ case ExpressionType.Parameter:
+ return this.VisitParameter((ParameterExpression)exp);
+ case ExpressionType.MemberAccess:
+ return this.VisitMemberAccess((MemberExpression)exp);
+ case ExpressionType.Call:
+ return this.VisitMethodCall((MethodCallExpression)exp);
+ case ExpressionType.Lambda:
+ return this.VisitLambda((LambdaExpression)exp);
+ case ExpressionType.New:
+ return this.VisitNew((NewExpression)exp);
+ case ExpressionType.NewArrayInit:
+ case ExpressionType.NewArrayBounds:
+ return this.VisitNewArray((NewArrayExpression)exp);
+ case ExpressionType.Invoke:
+ return this.VisitInvocation((InvocationExpression)exp);
+ case ExpressionType.MemberInit:
+ return this.VisitMemberInit((MemberInitExpression)exp);
+ case ExpressionType.ListInit:
+ return this.VisitListInit((ListInitExpression)exp);
+ default:
+ throw Error.UnhandledExpressionType(exp.NodeType);
+ }
+ }
+
+ internal virtual MemberBinding VisitBinding(MemberBinding binding)
+ {
+ switch (binding.BindingType)
+ {
+ case MemberBindingType.Assignment:
+ return this.VisitMemberAssignment((MemberAssignment)binding);
+ case MemberBindingType.MemberBinding:
+ return this.VisitMemberMemberBinding((MemberMemberBinding)binding);
+ case MemberBindingType.ListBinding:
+ return this.VisitMemberListBinding((MemberListBinding)binding);
+ default:
+ throw Error.UnhandledBindingType(binding.BindingType);
+ }
+ }
+
+ internal virtual ElementInit VisitElementInitializer(ElementInit initializer)
+ {
+ ReadOnlyCollection arguments = this.VisitExpressionList(initializer.Arguments);
+ if (arguments != initializer.Arguments)
+ {
+ return Expression.ElementInit(initializer.AddMethod, arguments);
+ }
+ return initializer;
+ }
+
+ internal virtual Expression VisitUnary(UnaryExpression u)
+ {
+ Expression operand = this.Visit(u.Operand);
+ if (operand != u.Operand)
+ {
+ return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
+ }
+ return u;
+ }
+
+ internal virtual Expression VisitBinary(BinaryExpression b)
+ {
+ Expression left = this.Visit(b.Left);
+ Expression right = this.Visit(b.Right);
+ Expression conversion = this.Visit(b.Conversion);
+ if (left != b.Left || right != b.Right || conversion != b.Conversion)
+ {
+ if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
+ return Expression.Coalesce(left, right, conversion as LambdaExpression);
+ else
+ return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
+ }
+ return b;
+ }
+
+ internal virtual Expression VisitTypeIs(TypeBinaryExpression b)
+ {
+ Expression expr = this.Visit(b.Expression);
+ if (expr != b.Expression)
+ {
+ return Expression.TypeIs(expr, b.TypeOperand);
+ }
+ return b;
+ }
+
+ internal virtual Expression VisitConstant(ConstantExpression c)
+ {
+ return c;
+ }
+
+ internal virtual Expression VisitConditional(ConditionalExpression c)
+ {
+ Expression test = this.Visit(c.Test);
+ Expression ifTrue = this.Visit(c.IfTrue);
+ Expression ifFalse = this.Visit(c.IfFalse);
+ if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse)
+ {
+ return Expression.Condition(test, ifTrue, ifFalse);
+ }
+ return c;
+ }
+
+ internal virtual Expression VisitParameter(ParameterExpression p)
+ {
+ return p;
+ }
+
+ internal virtual Expression VisitMemberAccess(MemberExpression m)
+ {
+ Expression exp = this.Visit(m.Expression);
+ if (exp != m.Expression)
+ {
+ return Expression.MakeMemberAccess(exp, m.Member);
+ }
+ return m;
+ }
+
+ internal virtual Expression VisitMethodCall(MethodCallExpression m)
+ {
+ Expression obj = this.Visit(m.Object);
+ IEnumerable args = this.VisitExpressionList(m.Arguments);
+ if (obj != m.Object || args != m.Arguments)
+ {
+ return Expression.Call(obj, m.Method, args);
+ }
+ return m;
+ }
+
+ internal virtual ReadOnlyCollection VisitExpressionList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ Expression p = this.Visit(original[i]);
+ if (list != null)
+ {
+ list.Add(p);
+ }
+ else if (p != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+ list.Add(p);
+ }
+ }
+ if (list != null)
+ return list.ToReadOnlyCollection();
+ return original;
+ }
+
+ internal virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
+ {
+ Expression e = this.Visit(assignment.Expression);
+ if (e != assignment.Expression)
+ {
+ return Expression.Bind(assignment.Member, e);
+ }
+ return assignment;
+ }
+
+ internal virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
+ {
+ IEnumerable bindings = this.VisitBindingList(binding.Bindings);
+ if (bindings != binding.Bindings)
+ {
+ return Expression.MemberBind(binding.Member, bindings);
+ }
+ return binding;
+ }
+
+ internal virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
+ {
+ IEnumerable initializers = this.VisitElementInitializerList(binding.Initializers);
+ if (initializers != binding.Initializers)
+ {
+ return Expression.ListBind(binding.Member, initializers);
+ }
+ return binding;
+ }
+
+ internal virtual IEnumerable VisitBindingList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ MemberBinding b = this.VisitBinding(original[i]);
+ if (list != null)
+ {
+ list.Add(b);
+ }
+ else if (b != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+ list.Add(b);
+ }
+ }
+ if (list != null)
+ return list;
+ return original;
+ }
+
+ internal virtual IEnumerable VisitElementInitializerList(ReadOnlyCollection original)
+ {
+ List list = null;
+ for (int i = 0, n = original.Count; i < n; i++)
+ {
+ ElementInit init = this.VisitElementInitializer(original[i]);
+ if (list != null)
+ {
+ list.Add(init);
+ }
+ else if (init != original[i])
+ {
+ list = new List(n);
+ for (int j = 0; j < i; j++)
+ {
+ list.Add(original[j]);
+ }
+ list.Add(init);
+ }
+ }
+ if (list != null)
+ return list;
+ return original;
+ }
+
+ internal virtual Expression VisitLambda(LambdaExpression lambda)
+ {
+ Expression body = this.Visit(lambda.Body);
+ if (body != lambda.Body)
+ {
+ return Expression.Lambda(lambda.Type, body, lambda.Parameters);
+ }
+ return lambda;
+ }
+
+ internal virtual NewExpression VisitNew(NewExpression nex)
+ {
+ IEnumerable args = this.VisitExpressionList(nex.Arguments);
+ if (args != nex.Arguments)
+ {
+ if (nex.Members != null)
+ return Expression.New(nex.Constructor, args, nex.Members);
+ else
+ return Expression.New(nex.Constructor, args);
+ }
+ return nex;
+ }
+
+ internal virtual Expression VisitMemberInit(MemberInitExpression init)
+ {
+ NewExpression n = this.VisitNew(init.NewExpression);
+ IEnumerable bindings = this.VisitBindingList(init.Bindings);
+ if (n != init.NewExpression || bindings != init.Bindings)
+ {
+ return Expression.MemberInit(n, bindings);
+ }
+ return init;
+ }
+
+ internal virtual Expression VisitListInit(ListInitExpression init)
+ {
+ NewExpression n = this.VisitNew(init.NewExpression);
+ IEnumerable initializers = this.VisitElementInitializerList(init.Initializers);
+ if (n != init.NewExpression || initializers != init.Initializers)
+ {
+ return Expression.ListInit(n, initializers);
+ }
+ return init;
+ }
+
+ internal virtual Expression VisitNewArray(NewArrayExpression na)
+ {
+ IEnumerable exprs = this.VisitExpressionList(na.Expressions);
+ if (exprs != na.Expressions)
+ {
+ if (na.NodeType == ExpressionType.NewArrayInit)
+ {
+ return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
+ }
+ else
+ {
+ return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
+ }
+ }
+ return na;
+ }
+
+ internal virtual Expression VisitInvocation(InvocationExpression iv)
+ {
+ IEnumerable args = this.VisitExpressionList(iv.Arguments);
+ Expression expr = this.Visit(iv.Expression);
+ if (args != iv.Arguments || expr != iv.Expression)
+ {
+ return Expression.Invoke(expr, args);
+ }
+ return iv;
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/Expressions/ReadOnlyCollectionExtensions.cs b/src/System.Linq.Queryable/src/System/Linq/Expressions/ReadOnlyCollectionExtensions.cs
new file mode 100644
index 000000000000..44995fa1dfc2
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/Expressions/ReadOnlyCollectionExtensions.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace System.Linq.Expressions
+{
+ internal static class ReadOnlyCollectionExtensions
+ {
+ internal static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable sequence)
+ {
+ if (sequence == null)
+ return DefaultReadOnlyCollection.Empty;
+ ReadOnlyCollection col = sequence as ReadOnlyCollection;
+ if (col != null)
+ return col;
+ return new ReadOnlyCollection(sequence.ToArray());
+ }
+ private static class DefaultReadOnlyCollection
+ {
+ private static volatile ReadOnlyCollection s_defaultCollection;
+ internal static ReadOnlyCollection Empty
+ {
+ get
+ {
+ if (s_defaultCollection == null)
+ s_defaultCollection = new ReadOnlyCollection(new T[] { });
+ return s_defaultCollection;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Linq.Queryable/src/System/Linq/Queryable.cs b/src/System.Linq.Queryable/src/System/Linq/Queryable.cs
new file mode 100644
index 000000000000..50936a4994b1
--- /dev/null
+++ b/src/System.Linq.Queryable/src/System/Linq/Queryable.cs
@@ -0,0 +1,1743 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace System.Linq
+{
+ public static class Queryable
+ {
+ public static IQueryable AsQueryable(this IEnumerable source)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (source is IQueryable)
+ return (IQueryable)source;
+ return new EnumerableQuery(source);
+ }
+
+ public static IQueryable AsQueryable(this IEnumerable source)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (source is IQueryable)
+ return (IQueryable)source;
+ Type enumType = TypeHelper.FindGenericType(typeof(IEnumerable<>), source.GetType());
+ if (enumType == null)
+ throw Error.ArgumentNotIEnumerableGeneric("source");
+ return EnumerableQuery.Create(enumType.GetTypeInfo().GenericTypeArguments[0], source);
+ }
+
+ public static IQueryable Where(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Where(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable Where(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Where(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable OfType(this IQueryable source)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.OfType(source)),
+ new Expression[] { source.Expression }
+ ));
+ }
+
+ public static IQueryable Cast(this IQueryable source)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Cast(source)),
+ new Expression[] { source.Expression }
+ ));
+ }
+
+ public static IQueryable Select(this IQueryable source, Expression> selector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (selector == null)
+ throw Error.ArgumentNull("selector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Select(source, selector)),
+ new Expression[] { source.Expression, Expression.Quote(selector) }
+ ));
+ }
+
+ public static IQueryable Select(this IQueryable source, Expression> selector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (selector == null)
+ throw Error.ArgumentNull("selector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Select(source, selector)),
+ new Expression[] { source.Expression, Expression.Quote(selector) }
+ ));
+ }
+
+ public static IQueryable SelectMany(this IQueryable source, Expression>> selector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (selector == null)
+ throw Error.ArgumentNull("selector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SelectMany(source, selector)),
+ new Expression[] { source.Expression, Expression.Quote(selector) }
+ ));
+ }
+
+ public static IQueryable SelectMany(this IQueryable source, Expression>> selector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (selector == null)
+ throw Error.ArgumentNull("selector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SelectMany(source, selector)),
+ new Expression[] { source.Expression, Expression.Quote(selector) }
+ ));
+ }
+
+ public static IQueryable SelectMany(this IQueryable source, Expression>> collectionSelector, Expression> resultSelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (collectionSelector == null)
+ throw Error.ArgumentNull("collectionSelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SelectMany(source, collectionSelector, resultSelector)),
+ new Expression[] { source.Expression, Expression.Quote(collectionSelector), Expression.Quote(resultSelector) }
+ ));
+ }
+
+ public static IQueryable SelectMany(this IQueryable source, Expression>> collectionSelector, Expression> resultSelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (collectionSelector == null)
+ throw Error.ArgumentNull("collectionSelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SelectMany(source, collectionSelector, resultSelector)),
+ new Expression[] { source.Expression, Expression.Quote(collectionSelector), Expression.Quote(resultSelector) }
+ ));
+ }
+
+ private static Expression GetSourceExpression(IEnumerable source)
+ {
+ IQueryable q = source as IQueryable;
+ if (q != null) return q.Expression;
+ return Expression.Constant(source, typeof(IEnumerable));
+ }
+
+ public static IQueryable Join(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression> resultSelector)
+ {
+ if (outer == null)
+ throw Error.ArgumentNull("outer");
+ if (inner == null)
+ throw Error.ArgumentNull("inner");
+ if (outerKeySelector == null)
+ throw Error.ArgumentNull("outerKeySelector");
+ if (innerKeySelector == null)
+ throw Error.ArgumentNull("innerKeySelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return outer.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Join(outer, inner, outerKeySelector, innerKeySelector, resultSelector)),
+ new Expression[] {
+ outer.Expression,
+ GetSourceExpression(inner),
+ Expression.Quote(outerKeySelector),
+ Expression.Quote(innerKeySelector),
+ Expression.Quote(resultSelector)
+ }
+ ));
+ }
+
+ public static IQueryable Join(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression> resultSelector, IEqualityComparer comparer)
+ {
+ if (outer == null)
+ throw Error.ArgumentNull("outer");
+ if (inner == null)
+ throw Error.ArgumentNull("inner");
+ if (outerKeySelector == null)
+ throw Error.ArgumentNull("outerKeySelector");
+ if (innerKeySelector == null)
+ throw Error.ArgumentNull("innerKeySelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return outer.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Join(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer)),
+ new Expression[] {
+ outer.Expression,
+ GetSourceExpression(inner),
+ Expression.Quote(outerKeySelector),
+ Expression.Quote(innerKeySelector),
+ Expression.Quote(resultSelector),
+ Expression.Constant(comparer, typeof(IEqualityComparer))
+ }
+ ));
+ }
+
+ public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression, TResult>> resultSelector)
+ {
+ if (outer == null)
+ throw Error.ArgumentNull("outer");
+ if (inner == null)
+ throw Error.ArgumentNull("inner");
+ if (outerKeySelector == null)
+ throw Error.ArgumentNull("outerKeySelector");
+ if (innerKeySelector == null)
+ throw Error.ArgumentNull("innerKeySelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return outer.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.GroupJoin(outer, inner, outerKeySelector, innerKeySelector, resultSelector)),
+ new Expression[] {
+ outer.Expression,
+ GetSourceExpression(inner),
+ Expression.Quote(outerKeySelector),
+ Expression.Quote(innerKeySelector),
+ Expression.Quote(resultSelector) }
+ ));
+ }
+
+ public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression, TResult>> resultSelector, IEqualityComparer comparer)
+ {
+ if (outer == null)
+ throw Error.ArgumentNull("outer");
+ if (inner == null)
+ throw Error.ArgumentNull("inner");
+ if (outerKeySelector == null)
+ throw Error.ArgumentNull("outerKeySelector");
+ if (innerKeySelector == null)
+ throw Error.ArgumentNull("innerKeySelector");
+ if (resultSelector == null)
+ throw Error.ArgumentNull("resultSelector");
+ return outer.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.GroupJoin(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer)),
+ new Expression[] {
+ outer.Expression,
+ GetSourceExpression(inner),
+ Expression.Quote(outerKeySelector),
+ Expression.Quote(innerKeySelector),
+ Expression.Quote(resultSelector),
+ Expression.Constant(comparer, typeof(IEqualityComparer)) }
+ ));
+ }
+
+ public static IOrderedQueryable OrderBy(this IQueryable source, Expression> keySelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.OrderBy(source, keySelector)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector) }
+ ));
+ }
+
+ public static IOrderedQueryable OrderBy(this IQueryable source, Expression> keySelector, IComparer comparer)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.OrderBy(source, keySelector, comparer)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)) }
+ ));
+ }
+
+ public static IOrderedQueryable OrderByDescending(this IQueryable source, Expression> keySelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.OrderByDescending(source, keySelector)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector) }
+ ));
+ }
+
+ public static IOrderedQueryable OrderByDescending(this IQueryable source, Expression> keySelector, IComparer comparer)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.OrderByDescending(source, keySelector, comparer)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)) }
+ ));
+ }
+
+ public static IOrderedQueryable ThenBy(this IOrderedQueryable source, Expression> keySelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.ThenBy(source, keySelector)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector) }
+ ));
+ }
+
+ public static IOrderedQueryable ThenBy(this IOrderedQueryable source, Expression> keySelector, IComparer comparer)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.ThenBy(source, keySelector, comparer)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)) }
+ ));
+ }
+
+ public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, Expression> keySelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.ThenByDescending(source, keySelector)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector) }
+ ));
+ }
+
+ public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, Expression> keySelector, IComparer comparer)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return (IOrderedQueryable)source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.ThenByDescending(source, keySelector, comparer)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Constant(comparer, typeof(IComparer)) }
+ ));
+ }
+
+ public static IQueryable Take(this IQueryable source, int count)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Take(source, count)),
+ new Expression[] { source.Expression, Expression.Constant(count) }
+ ));
+ }
+
+ public static IQueryable TakeWhile(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.TakeWhile(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable TakeWhile(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.TakeWhile(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable Skip(this IQueryable source, int count)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.Skip(source, count)),
+ new Expression[] { source.Expression, Expression.Constant(count) }
+ ));
+ }
+
+ public static IQueryable SkipWhile(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SkipWhile(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable SkipWhile(this IQueryable source, Expression> predicate)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (predicate == null)
+ throw Error.ArgumentNull("predicate");
+ return source.Provider.CreateQuery(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.SkipWhile(source, predicate)),
+ new Expression[] { source.Expression, Expression.Quote(predicate) }
+ ));
+ }
+
+ public static IQueryable> GroupBy(this IQueryable source, Expression> keySelector)
+ {
+ if (source == null)
+ throw Error.ArgumentNull("source");
+ if (keySelector == null)
+ throw Error.ArgumentNull("keySelector");
+ return source.Provider.CreateQuery>(
+ Expression.Call(
+ null,
+ GetMethodInfoOf(() => Queryable.GroupBy(source, keySelector)),
+ new Expression[] { source.Expression, Expression.Quote(keySelector) }
+ ));
+ }
+
+ public static IQueryable> GroupBy(this IQueryable source, Expression