-//\r
-// QueryableEnumerable<TElement>.cs\r
-//\r
-// Authors:\r
-// Roei Erez (roeie@mainsoft.com)\r
-//\r
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)\r
-//\r
-// Permission is hereby granted, free of charge, to any person obtaining\r
-// a copy of this software and associated documentation files (the\r
-// "Software"), to deal in the Software without restriction, including\r
-// without limitation the rights to use, copy, modify, merge, publish,\r
-// distribute, sublicense, and/or sell copies of the Software, and to\r
-// permit persons to whom the Software is furnished to do so, subject to\r
-// the following conditions:\r
-//\r
-// The above copyright notice and this permission notice shall be\r
-// included in all copies or substantial portions of the Software.\r
-//\r
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
-//\r
-\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Linq.Expressions;\r
-\r
-namespace System.Linq\r
-{\r
- internal class QueryableEnumerable<TElement> : IQueryable<TElement>, IQueryProvider, IOrderedQueryable<TElement>\r
- { \r
- Expression expression;\r
-\r
- public QueryableEnumerable (Expression expression) {\r
- this.expression = expression;\r
- }\r
-\r
- public Type ElementType {\r
- get { return expression.Type; }\r
- }\r
-\r
- public Expression Expression {\r
- get { return expression; }\r
- }\r
-\r
- public IQueryProvider Provider {\r
- get { return this; }\r
- }\r
-\r
- public System.Collections.IEnumerator GetEnumerator () \r
- { \r
- return ((IEnumerable<TElement>)this).GetEnumerator ();\r
- }\r
-\r
- IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator () \r
- {\r
- return Execute<IEnumerable<TElement>> (Expression).GetEnumerator ();\r
- }\r
-\r
- public IQueryable CreateQuery (System.Linq.Expressions.Expression expression) \r
- {\r
- return (IQueryable) Activator.CreateInstance (\r
- typeof (QueryableEnumerable<>).MakeGenericType (expression.Type.GetGenericArguments()[0]), expression); \r
- }\r
-\r
- public object Execute (System.Linq.Expressions.Expression expression) \r
- {\r
- QueryableTransformer visitor = new QueryableTransformer ();\r
- Expression body = visitor.Transform (expression);\r
- LambdaExpression lambda = Expression.Lambda (body); \r
- return lambda.Compile ().DynamicInvoke();\r
- }\r
-\r
- public IQueryable<TElem> CreateQuery<TElem> (System.Linq.Expressions.Expression expression) \r
- {\r
- return new QueryableEnumerable<TElem> (expression);\r
- }\r
-\r
- public TResult Execute<TResult> (System.Linq.Expressions.Expression expression) \r
- {\r
- QueryableTransformer visitor = new QueryableTransformer ();\r
- Expression body = visitor.Transform (expression);\r
- Expression<Func<TResult>> lambda = Expression.Lambda<Func<TResult>> (body);\r
- return lambda.Compile () ();\r
- }\r
- }\r
-}\r
+//
+// QueryableEnumerable<TElement>.cs
+//
+// Authors:
+// Roei Erez (roeie@mainsoft.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+
+namespace System.Linq {
+
+ class QueryableEnumerable<TElement> : IQueryable<TElement>, IQueryProvider, IOrderedQueryable<TElement> {
+
+ Expression expression;
+
+ public Type ElementType {
+ get { return expression.Type; }
+ }
+
+ public Expression Expression {
+ get { return expression; }
+ }
+
+ public IQueryProvider Provider {
+ get { return this; }
+ }
+
+ public QueryableEnumerable (Expression expression)
+ {
+ this.expression = expression;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return GetEnumerator ();
+ }
+
+ public IEnumerator<TElement> GetEnumerator ()
+ {
+ return Execute<IEnumerable<TElement>> (expression).GetEnumerator ();
+ }
+
+ public IQueryable CreateQuery (Expression expression)
+ {
+ return (IQueryable) Activator.CreateInstance (
+ typeof (QueryableEnumerable<>).MakeGenericType (
+ expression.Type.GetFirstGenericArgument ()), expression);
+ }
+
+ public object Execute (Expression expression)
+ {
+ var lambda = Expression.Lambda (TransformQueryable (expression));
+ return lambda.Compile ().DynamicInvoke ();
+ }
+
+ static Expression TransformQueryable (Expression expression)
+ {
+ return new QueryableTransformer ().Transform (expression);
+ }
+
+ public IQueryable<TElem> CreateQuery<TElem> (Expression expression)
+ {
+ return new QueryableEnumerable<TElem> (expression);
+ }
+
+ public TResult Execute<TResult> (Expression expression)
+ {
+ var lambda = Expression.Lambda<Func<TResult>> (TransformQueryable (expression));
+ return lambda.Compile ().Invoke ();
+ }
+ }
+}
-//\r
-// QueryableTransformer.cs\r
-//\r
-// Authors:\r
-// Roei Erez (roeie@mainsoft.com)\r
-//\r
-// Copyright (C) 2007 Novell, Inc (http://www.novell.com)\r
-//\r
-// Permission is hereby granted, free of charge, to any person obtaining\r
-// a copy of this software and associated documentation files (the\r
-// "Software"), to deal in the Software without restriction, including\r
-// without limitation the rights to use, copy, modify, merge, publish,\r
-// distribute, sublicense, and/or sell copies of the Software, and to\r
-// permit persons to whom the Software is furnished to do so, subject to\r
-// the following conditions:\r
-//\r
-// The above copyright notice and this permission notice shall be\r
-// included in all copies or substantial portions of the Software.\r
-//\r
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
-//\r
-\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Linq.Expressions;\r
-using System.Reflection;\r
-using System.Runtime.CompilerServices;\r
-using System.Collections.ObjectModel;\r
-\r
-namespace System.Linq\r
-{\r
- internal class QueryableTransformer : ExpressionTransformer\r
- { \r
-\r
- internal QueryableTransformer () {}\r
- \r
- protected override MethodCallExpression VisitMethodCall (MethodCallExpression methodCall) \r
- { \r
- if ( IsQueryableExtension ( methodCall.Method ))\r
- {\r
- return ReplaceIQueryableMethod (methodCall);\r
- }\r
- return base.VisitMethodCall (methodCall);\r
- }\r
-\r
- protected override LambdaExpression VisitLambda (LambdaExpression lambda) \r
- {\r
- return lambda;\r
- } \r
-\r
- bool IsQueryableExtension (MethodInfo method) \r
- {\r
- return method.GetCustomAttributes(typeof(ExtensionAttribute), false).Count() > 0 && \r
- typeof(IQueryable).IsAssignableFrom( method.GetParameters () [0].ParameterType );\r
- }\r
-\r
- MethodCallExpression ReplaceIQueryableMethod (MethodCallExpression oldCall)\r
- { \r
- Expression target = null;\r
- if (oldCall.Object != null){\r
- target = Visit (oldCall.Object);\r
- } \r
- MethodInfo newMethod = ReplaceIQueryableMethodInfo(oldCall.Method);\r
-\r
- Expression [] args = new Expression [oldCall.Arguments.Count];\r
- int counter = 0;\r
- foreach (Expression e in oldCall.Arguments) { \r
- Type methodParam = newMethod.GetParameters() [counter].ParameterType; \r
- args [counter++] = ReplaceQuotedLambdaIfNeeded(Visit (e), methodParam);\r
- }\r
- ReadOnlyCollection<Expression> col = args.ToReadOnlyCollection();\r
- MethodCallExpression newMethodCall = new MethodCallExpression (target, newMethod, col);\r
- return newMethodCall;\r
- }\r
-\r
- static Expression ReplaceQuotedLambdaIfNeeded (Expression e, Type delegateType)\r
- {\r
- UnaryExpression unary = e as UnaryExpression;\r
- if (unary != null) {\r
- LambdaExpression lambda = unary.Operand as LambdaExpression;\r
- if (lambda != null && lambda.Type == delegateType)\r
- return lambda;\r
- }\r
- return e;\r
- }\r
-\r
- static MethodInfo ReplaceIQueryableMethodInfo (MethodInfo qm) \r
- {\r
- Type typeToSearch = qm.DeclaringType == typeof (Queryable) ? typeof (Enumerable) : qm.DeclaringType;\r
- MethodInfo result = GetMatchingMethod (qm, typeToSearch); \r
- if (result == null)\r
- throw new InvalidOperationException (\r
- string.Format("There is no method {0} on type {1} that matches the specified arguments", \r
- qm.Name, \r
- qm.DeclaringType.FullName));\r
- return result;\r
- }\r
-\r
- static MethodInfo GetMatchingMethod (MethodInfo qm, Type fromType)\r
- {\r
- MethodInfo result = (from em in fromType.GetMethods ()\r
- where Match (em, qm)\r
- select em)\r
- .FirstOrDefault ();\r
- if (result != null && qm.IsGenericMethod)\r
- result = result.MakeGenericMethod (qm.GetGenericArguments ());\r
- return result;\r
- }\r
-\r
- static bool Match (MethodInfo em, MethodInfo qm) {\r
-\r
- if (em.GetCustomAttributes (typeof (ExtensionAttribute), false).Count() == 0)\r
- return false;\r
-\r
- if (em.Name != qm.Name)\r
- return false; \r
-\r
- if (em.GetGenericArguments ().Length != qm.GetGenericArguments ().Length)\r
- return false; \r
-\r
- Type [] parameters = (from p in qm.GetParameters () select p.ParameterType).ToArray ();\r
- Type returnType = qm.ReturnType;\r
- \r
- if (parameters.Length != em.GetParameters ().Length)\r
- return false;\r
-\r
- MethodInfo instanceMethod = em;\r
- if (qm.IsGenericMethod) {\r
- if (!qm.IsGenericMethod)\r
- return false;\r
- if (em.GetParameters ().Length != qm.GetParameters ().Length)\r
- return false;\r
- Type [] genArgs = qm.GetGenericArguments ();\r
- instanceMethod = em.MakeGenericMethod (genArgs);\r
- }\r
-\r
- Type [] enumerableParams = (from p in instanceMethod.GetParameters () select p.ParameterType).ToArray ();\r
-\r
- if (enumerableParams [0] != ConvertParameter (parameters [0]))\r
- return false;\r
- for (int i = 1; i < enumerableParams.Length; ++i)\r
- if (!ArgumentMatch(enumerableParams [i], parameters [i]))\r
- return false;\r
- if (!ArgumentMatch(instanceMethod.ReturnType, returnType))\r
- return false;\r
- return true;\r
- }\r
-\r
- static bool ArgumentMatch (Type enumerableParam, Type queryableParam)\r
- {\r
- return enumerableParam == queryableParam || enumerableParam == ConvertParameter (queryableParam);\r
- }\r
-\r
- static Type ConvertParameter (Type type) \r
- {\r
- if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IQueryable<>))\r
- type = typeof (IEnumerable<>).MakeGenericType (type.GetGenericArguments ());\r
- else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IOrderedQueryable<>))\r
- type = typeof (IOrderedEnumerable<>).MakeGenericType (type.GetGenericArguments ());\r
- else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Expression<>))\r
- type = type.GetGenericArguments () [0];\r
- else if (type == typeof (IQueryable))\r
- type = typeof (System.Collections.IEnumerable);\r
- return type;\r
- } \r
- }\r
-}\r
+//
+// QueryableTransformer.cs
+//
+// Authors:
+// Roei Erez (roeie@mainsoft.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Collections.ObjectModel;
+
+namespace System.Linq
+{
+ internal class QueryableTransformer : ExpressionTransformer
+ {
+
+ internal QueryableTransformer () {}
+
+ protected override MethodCallExpression VisitMethodCall (MethodCallExpression methodCall)
+ {
+ if ( IsQueryableExtension ( methodCall.Method ))
+ {
+ return ReplaceIQueryableMethod (methodCall);
+ }
+ return base.VisitMethodCall (methodCall);
+ }
+
+ protected override LambdaExpression VisitLambda (LambdaExpression lambda)
+ {
+ return lambda;
+ }
+
+ bool IsQueryableExtension (MethodInfo method)
+ {
+ return method.GetCustomAttributes(typeof(ExtensionAttribute), false).Count() > 0 &&
+ typeof(IQueryable).IsAssignableFrom( method.GetParameters () [0].ParameterType );
+ }
+
+ MethodCallExpression ReplaceIQueryableMethod (MethodCallExpression oldCall)
+ {
+ Expression target = null;
+ if (oldCall.Object != null){
+ target = Visit (oldCall.Object);
+ }
+ MethodInfo newMethod = ReplaceIQueryableMethodInfo(oldCall.Method);
+
+ Expression [] args = new Expression [oldCall.Arguments.Count];
+ int counter = 0;
+ foreach (Expression e in oldCall.Arguments) {
+ Type methodParam = newMethod.GetParameters() [counter].ParameterType;
+ args [counter++] = ReplaceQuotedLambdaIfNeeded(Visit (e), methodParam);
+ }
+ ReadOnlyCollection<Expression> col = args.ToReadOnlyCollection();
+ MethodCallExpression newMethodCall = new MethodCallExpression (target, newMethod, col);
+ return newMethodCall;
+ }
+
+ static Expression ReplaceQuotedLambdaIfNeeded (Expression e, Type delegateType)
+ {
+ UnaryExpression unary = e as UnaryExpression;
+ if (unary != null) {
+ LambdaExpression lambda = unary.Operand as LambdaExpression;
+ if (lambda != null && lambda.Type == delegateType)
+ return lambda;
+ }
+ return e;
+ }
+
+ static MethodInfo ReplaceIQueryableMethodInfo (MethodInfo qm)
+ {
+ Type typeToSearch = qm.DeclaringType == typeof (Queryable) ? typeof (Enumerable) : qm.DeclaringType;
+ MethodInfo result = GetMatchingMethod (qm, typeToSearch);
+ if (result == null)
+ throw new InvalidOperationException (
+ string.Format("There is no method {0} on type {1} that matches the specified arguments",
+ qm.Name,
+ qm.DeclaringType.FullName));
+ return result;
+ }
+
+ static MethodInfo GetMatchingMethod (MethodInfo qm, Type fromType)
+ {
+ MethodInfo result = (from em in fromType.GetMethods ()
+ where Match (em, qm)
+ select em)
+ .FirstOrDefault ();
+ if (result != null && qm.IsGenericMethod)
+ result = result.MakeGenericMethod (qm.GetGenericArguments ());
+ return result;
+ }
+
+ static bool Match (MethodInfo em, MethodInfo qm) {
+
+ if (em.GetCustomAttributes (typeof (ExtensionAttribute), false).Count() == 0)
+ return false;
+
+ if (em.Name != qm.Name)
+ return false;
+
+ if (em.GetGenericArguments ().Length != qm.GetGenericArguments ().Length)
+ return false;
+
+ Type [] parameters = (from p in qm.GetParameters () select p.ParameterType).ToArray ();
+ Type returnType = qm.ReturnType;
+
+ if (parameters.Length != em.GetParameters ().Length)
+ return false;
+
+ MethodInfo instanceMethod = em;
+ if (qm.IsGenericMethod) {
+ if (!qm.IsGenericMethod)
+ return false;
+ if (em.GetParameters ().Length != qm.GetParameters ().Length)
+ return false;
+ Type [] genArgs = qm.GetGenericArguments ();
+ instanceMethod = em.MakeGenericMethod (genArgs);
+ }
+
+ Type [] enumerableParams = (from p in instanceMethod.GetParameters () select p.ParameterType).ToArray ();
+
+ if (enumerableParams [0] != ConvertParameter (parameters [0]))
+ return false;
+ for (int i = 1; i < enumerableParams.Length; ++i)
+ if (!ArgumentMatch(enumerableParams [i], parameters [i]))
+ return false;
+ if (!ArgumentMatch(instanceMethod.ReturnType, returnType))
+ return false;
+ return true;
+ }
+
+ static bool ArgumentMatch (Type enumerableParam, Type queryableParam)
+ {
+ return enumerableParam == queryableParam || enumerableParam == ConvertParameter (queryableParam);
+ }
+
+ static Type ConvertParameter (Type type)
+ {
+ if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IQueryable<>))
+ type = typeof (IEnumerable<>).MakeGenericType (type.GetGenericArguments ());
+ else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (IOrderedQueryable<>))
+ type = typeof (IOrderedEnumerable<>).MakeGenericType (type.GetGenericArguments ());
+ else if (type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Expression<>))
+ type = type.GetGenericArguments () [0];
+ else if (type == typeof (IQueryable))
+ type = typeof (System.Collections.IEnumerable);
+ return type;
+ }
+ }
+}