Files
Dec2017-Script-Dump/System.Core/System/Linq/QueryableTransformer.cs
T
2026-06-04 11:42:34 +02:00

202 lines
6.1 KiB
C#

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<Expression>());
}
// 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;
}
}
}