/// <summary> /// Rewrites the given expression to use the specified type as root. /// </summary> /// <param name="expression"> /// The expression. /// </param> /// <param name="delegateType"> /// The delegate type. /// </param> /// <param name="paramTypes"> /// The parameter types. /// </param> /// <returns> /// The rewritten expression. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="expression" /> is null. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expression" /> has zero or more than two parameters -or- <paramref name="expression" /> /// has two parameters but the second parameter is not a <see cref="WhereDelegate" />. /// </exception> protected virtual LambdaExpression GetLambdaExpression ( LambdaExpression expression, Type delegateType, params Type[] paramTypes ) { if (expression == null) { throw new ArgumentNullException("expression"); } int count = expression.Parameters.Count; if (count != 1 && !(count == 2 && expression.Parameters.Last().Type == typeof(WhereDelegate))) { throw new ArgumentException ( "expression must have 1 param, or 2 param if last is WhereDelegate.", "expression" ); } var visitor = new ParameterReplaceVisitor(expression.Parameters[0], Expression.Parameter(_type, _alias)); Expression visited = visitor.Visit(expression.Body); var parameters = new List <ParameterExpression> { Expression.Parameter(paramTypes[0], "x") }; if (paramTypes.Length == 2) { var param = expression.Parameters[1]; var newParam = Expression.Parameter(param.Type, "where"); visitor = new ParameterReplaceVisitor(param, newParam); visited = visitor.Visit(visited); parameters.Add(newParam); } return(Expression.Lambda(delegateType, visited, parameters)); }
/// <summary> /// Combines (merges) the provided expressions into one. /// </summary> /// <param name="expressions"> /// The expressions to merge. /// </param> /// <typeparam name="TSource"> /// The <see cref="System.Type" /> of the source entity. /// </typeparam> /// <typeparam name="TDestination"> /// The <see cref="System.Type" /> of the result. /// </typeparam> /// <returns> /// The resulting expression. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="expressions" /> is null. /// </exception> /// <exception cref="ArgumentException"> /// If one or more of the provided expressions is neither of <see cref="MemberInitExpression" /> or /// <see cref="NewExpression" />, or if any but the first expression is a <see cref="NewExpression" />. /// </exception> public static Expression <Func <TSource, TDestination> > Combine <TSource, TDestination> ( params Expression <Func <TSource, TDestination> >[] expressions ) { if (expressions == null) { throw new ArgumentNullException("expressions"); } bool allAreMemberInit = expressions .Where(x => x != null) .Skip(1) // skip first which may also be a NewExpression .All(x => x.Body is MemberInitExpression); if (!allAreMemberInit) { throw new ArgumentException ( "All expressions must be MemberInitExpression except the first which can also be a NewExpression", "expressions" ); } Expression first = expressions[0].Body; NewExpression constructor; var bindings = new List <MemberBinding>(); if (first.NodeType == ExpressionType.MemberInit) { var initializer = (MemberInitExpression)first; constructor = initializer.NewExpression; bindings.AddRange(initializer.Bindings.OfType <MemberAssignment>()); } else if (first.NodeType == ExpressionType.New) { constructor = (NewExpression)first; } else { throw new ArgumentException ( "The first expression is not a MemberInitExpression, nor is it a NewExpression", "expressions" ); } ParameterExpression parameter = expressions[0].Parameters[0]; for (int i = 1; i < expressions.Length; i++) { if (expressions[i] == null) { continue; } var initializer = (MemberInitExpression)expressions[i].Body; var replace = new ParameterReplaceVisitor(expressions[i].Parameters[0], parameter); foreach (MemberAssignment binding in initializer.Bindings.OfType <MemberAssignment>()) { Expression converted = replace.VisitAndConvert(binding.Expression, "Combine"); if (converted != null) { MemberAssignment assignment = Expression.Bind(binding.Member, converted); bindings.Add(assignment); } } } MemberInitExpression combined = Expression.MemberInit(constructor, bindings); return(Expression.Lambda <Func <TSource, TDestination> >(combined, parameter)); }