public static bool Contains(ParameterExpression param, Expression expr) { FreeParameters freeParams = new FreeParameters(); freeParams.Visit(expr); return freeParams.Parameters.Contains(param); }
public static LambdaExpression Rewrite(LambdaExpression expr, LambdaExpression selector, Substitution pSubst) { if (expr != null) { Type resultType = selector.Body.Type; ParameterExpression resultParam = Expression.Parameter(resultType, "key_1"); // Perform substitutions ExpressionSubst subst = new ExpressionSubst(pSubst); subst.AddSubst(selector.Body, resultParam); if (selector.Body is NewExpression) { NewExpression newBody = (NewExpression)selector.Body; if (newBody.Constructor != null) { resultType = newBody.Constructor.DeclaringType; } if (TypeSystem.IsAnonymousType(resultType)) { PropertyInfo[] props = resultType.GetProperties(); //the following test is never expected to occur, and an assert would most likely suffice. if (props.Length != newBody.Arguments.Count) { throw new DryadLinqException(DryadLinqErrorCode.Internal, SR.BugInHandlingAnonymousClass); } for (int i = 0; i < props.Length; i++) { Expression leftExpr = newBody.Arguments[i]; Expression rightExpr = CreateMemberAccess(resultParam, props[i].Name); subst.AddSubst(leftExpr, rightExpr); } } } if (selector.Body is MemberInitExpression) { ReadOnlyCollection<MemberBinding> bindings = ((MemberInitExpression)selector.Body).Bindings; for (int i = 0; i < bindings.Count; i++) { if (bindings[i] is MemberAssignment) { Expression leftExpr = ((MemberAssignment)bindings[i]).Expression; Expression rightExpr = CreateMemberAccess(resultParam, ((MemberAssignment)bindings[i]).Member.Name); subst.AddSubst(leftExpr, rightExpr); } } } else { FieldMappingAttribute[] attribs = AttributeSystem.GetFieldMappingAttribs(selector); if (attribs != null) { foreach (FieldMappingAttribute attrib in attribs) { string[] srcFieldNames = attrib.Source.Split('.'); string paramName = srcFieldNames[0]; ParameterInfo[] paramInfos = null; if (selector.Body is MethodCallExpression) { paramInfos = ((MethodCallExpression)selector.Body).Method.GetParameters(); } else if (selector.Body is NewExpression) { paramInfos = ((NewExpression)selector.Body).Constructor.GetParameters(); } if (paramInfos != null) { int argIdx = -1; for (int i = 0; i < paramInfos.Length; i++) { if (paramInfos[i].Name == paramName) { argIdx = i; break; } } Expression leftExpr = null; if (argIdx != -1) { if (selector.Body is MethodCallExpression) { leftExpr = ((MethodCallExpression)selector.Body).Arguments[argIdx]; } else if (selector.Body is NewExpression) { leftExpr = ((NewExpression)selector.Body).Arguments[argIdx]; } } if (leftExpr == null) { throw new DryadLinqException(DryadLinqErrorCode.Internal, "The source of the FieldMapping annotation was wrong. " + paramName + " is not a formal parameter."); } string[] fieldNames = new string[srcFieldNames.Length - 1]; for (int i = 1; i < srcFieldNames.Length; i++) { fieldNames[i] = srcFieldNames[i-1]; } leftExpr = CreateMemberAccess(leftExpr, fieldNames); Expression rightExpr = CreateMemberAccess(resultParam, attrib.Destination.Split('.')); subst.AddSubst(leftExpr, rightExpr); } } } } Expression resultBody = subst.Visit(expr.Body); // Check if the substitutions are complete FreeParameters freeParams = new FreeParameters(); freeParams.Visit(resultBody); if (freeParams.Parameters.Count == 1 && freeParams.Parameters.Contains(resultParam)) { Type funcType = typeof(Func<,>).MakeGenericType(resultType, expr.Body.Type); return Expression.Lambda(funcType, resultBody, resultParam); } } return null; }