コード例 #1
0
        /// <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));
        }
コード例 #2
0
        /// <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));
        }