cleol + props
authorJb Evain <jbevain@gmail.com>
Thu, 15 May 2008 13:07:17 +0000 (13:07 -0000)
committerJb Evain <jbevain@gmail.com>
Thu, 15 May 2008 13:07:17 +0000 (13:07 -0000)
svn path=/trunk/mcs/; revision=103271

mcs/class/System.Core/System.Linq/Queryable.cs
mcs/class/System.Core/System.Linq/QueryableEnumerable.cs
mcs/class/System.Core/System.Linq/QueryableTransformer.cs

index dd08ebe241d18bb8f570a92e40f1637897e91e33..3ac735cacb527e21d5af3284f407028e031699ff 100644 (file)
@@ -137,14 +137,14 @@ namespace System.Linq {
 
                #region AsQueryable
 
-               [MonoTODO]
                public static IQueryable<TElement> AsQueryable<TElement> (this IEnumerable<TElement> source)
                {
                        var queryable = source as IQueryable<TElement>;
                        if (queryable != null)
                                return queryable;
 
-                       return new QueryableEnumerable<TElement> (new ConstantExpression (source, typeof (IQueryable<TElement>)));
+                       return new QueryableEnumerable<TElement> (
+                               Expression.Constant (source, typeof (IQueryable<TElement>)));
                }
 
                [MonoTODO]
index 47078033f7bb339aaca5ef38de781c1b756b26c5..1f6426f158d106e8f7e71dd3139c18895205ca97 100644 (file)
@@ -1,94 +1,97 @@
-//\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 ();
+               }
+       }
+}
index c680af99f1550d62aefbb4e6d150f85174e0c5fd..5fe97a45e91e45d4b2063c502872e63cb6695aac 100644 (file)
-//\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;
+               }
+       }
+}