using System; using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; namespace System.Linq { // Token: 0x02000046 RID: 70 internal class QueryableTransformer : ExpressionTransformer { // Token: 0x06000431 RID: 1073 RVA: 0x00013E84 File Offset: 0x00012084 protected override Expression VisitMethodCall(MethodCallExpression methodCall) { if (QueryableTransformer.IsQueryableExtension(methodCall.Method)) { return this.ReplaceQueryableMethod(methodCall); } return base.VisitMethodCall(methodCall); } // Token: 0x06000432 RID: 1074 RVA: 0x00013EB0 File Offset: 0x000120B0 protected override Expression VisitLambda(LambdaExpression lambda) { return lambda; } // Token: 0x06000433 RID: 1075 RVA: 0x00013EB4 File Offset: 0x000120B4 protected override Expression VisitConstant(ConstantExpression constant) { IQueryableEnumerable queryableEnumerable = constant.Value as IQueryableEnumerable; if (queryableEnumerable == null) { return constant; } return Expression.Constant(queryableEnumerable.GetEnumerable()); } // Token: 0x06000434 RID: 1076 RVA: 0x00013EE0 File Offset: 0x000120E0 private static bool IsQueryableExtension(MethodInfo method) { return QueryableTransformer.HasExtensionAttribute(method) && method.GetParameters()[0].ParameterType.IsAssignableTo(typeof(IQueryable)); } // Token: 0x06000435 RID: 1077 RVA: 0x00013F18 File Offset: 0x00012118 private static bool HasExtensionAttribute(MethodInfo method) { return method.GetCustomAttributes(typeof(ExtensionAttribute), false).Length > 0; } // Token: 0x06000436 RID: 1078 RVA: 0x00013F30 File Offset: 0x00012130 private MethodCallExpression ReplaceQueryableMethod(MethodCallExpression old) { Expression expression = null; if (old.Object != null) { expression = this.Visit(old.Object); } MethodInfo methodInfo = QueryableTransformer.ReplaceQueryableMethod(old.Method); ParameterInfo[] parameters = methodInfo.GetParameters(); Expression[] array = new Expression[old.Arguments.Count]; for (int i = 0; i < array.Length; i++) { array[i] = QueryableTransformer.UnquoteIfNeeded(this.Visit(old.Arguments[i]), parameters[i].ParameterType); } return new MethodCallExpression(expression, methodInfo, array.ToReadOnlyCollection()); } // Token: 0x06000437 RID: 1079 RVA: 0x00013FC8 File Offset: 0x000121C8 private static Expression UnquoteIfNeeded(Expression expression, Type delegateType) { if (expression.NodeType != ExpressionType.Quote) { return expression; } LambdaExpression lambdaExpression = (LambdaExpression)((UnaryExpression)expression).Operand; if (lambdaExpression.Type == delegateType) { return lambdaExpression; } return expression; } // Token: 0x06000438 RID: 1080 RVA: 0x00014004 File Offset: 0x00012204 private static Type GetTargetDeclaringType(MethodInfo method) { return (method.DeclaringType != typeof(Queryable)) ? method.DeclaringType : typeof(Enumerable); } // Token: 0x06000439 RID: 1081 RVA: 0x0001403C File Offset: 0x0001223C private static MethodInfo ReplaceQueryableMethod(MethodInfo method) { MethodInfo matchingMethod = QueryableTransformer.GetMatchingMethod(method, QueryableTransformer.GetTargetDeclaringType(method)); if (matchingMethod != null) { return matchingMethod; } throw new InvalidOperationException(string.Format("There is no method {0} on type {1} that matches the specified arguments", method.Name, method.DeclaringType.FullName)); } // Token: 0x0600043A RID: 1082 RVA: 0x00014080 File Offset: 0x00012280 private static MethodInfo GetMatchingMethod(MethodInfo method, Type declaring) { MethodInfo[] methods = declaring.GetMethods(); int i = 0; while (i < methods.Length) { MethodInfo methodInfo = methods[i]; if (!QueryableTransformer.MethodMatch(methodInfo, method)) { i++; } else { if (method.IsGenericMethod) { return methodInfo.MakeGenericMethodFrom(method); } return methodInfo; } } return null; } // Token: 0x0600043B RID: 1083 RVA: 0x000140D4 File Offset: 0x000122D4 private static bool MethodMatch(MethodInfo candidate, MethodInfo method) { if (candidate.Name != method.Name) { return false; } if (!QueryableTransformer.HasExtensionAttribute(candidate)) { return false; } Type[] parameterTypes = method.GetParameterTypes(); if (parameterTypes.Length != candidate.GetParameters().Length) { return false; } if (method.IsGenericMethod) { if (!candidate.IsGenericMethod) { return false; } if (candidate.GetGenericArguments().Length != method.GetGenericArguments().Length) { return false; } candidate = candidate.MakeGenericMethodFrom(method); } if (!QueryableTransformer.TypeMatch(candidate.ReturnType, method.ReturnType)) { return false; } Type[] parameterTypes2 = candidate.GetParameterTypes(); if (parameterTypes2[0] != QueryableTransformer.GetComparableType(parameterTypes[0])) { return false; } for (int i = 1; i < parameterTypes2.Length; i++) { if (!QueryableTransformer.TypeMatch(parameterTypes2[i], parameterTypes[i])) { return false; } } return true; } // Token: 0x0600043C RID: 1084 RVA: 0x000141B0 File Offset: 0x000123B0 private static bool TypeMatch(Type candidate, Type type) { return candidate == type || candidate == QueryableTransformer.GetComparableType(type); } // Token: 0x0600043D RID: 1085 RVA: 0x000141C4 File Offset: 0x000123C4 private static Type GetComparableType(Type type) { if (type.IsGenericInstanceOf(typeof(IQueryable<>))) { type = typeof(IEnumerable<>).MakeGenericTypeFrom(type); } else if (type.IsGenericInstanceOf(typeof(IOrderedQueryable<>))) { type = typeof(IOrderedEnumerable<>).MakeGenericTypeFrom(type); } else if (type.IsGenericInstanceOf(typeof(Expression<>))) { type = type.GetFirstGenericArgument(); } else if (type == typeof(IQueryable)) { type = typeof(IEnumerable); } return type; } } }