Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to change the type of the parameter in an Expression?

since i am using POCOS in my domain, i want my repository to be able to received Expression filters of the type of my POCOS and change the parameter in the expression to be the of type of my LINQ tables, my fields have the same name as my members so i was able to accomplish this for 1 and 2 lambda conditions by breaking into members and constants, if i add more conditions this lead to recursively parse the binary expression.

this is how i ended, is there an easy way to accomplish this

var q = from p in 
        db.products.Where(ExpressionBuilder.Create<MyPocoProduct,LinqProduct>(myPocoProductExpression))

the way i change it

public class ExpressionBuilder
    {
        public static Expression<Func<TLinq, bool>> Create<TEntity, TLinq>(Expression<Func<TEntity, bool>> predicate)
        {

            try
            {
                //get the predicate body
                var binaryExpr = (BinaryExpression)predicate.Body;

                //holds the resuting Expression
                var expressionResult = default(BinaryExpression);

                // Create the parameter of the Linq table Type 
                ParameterExpression parameter = Expression.Parameter(typeof(TLinq), predicate.Parameters[0].Name);


                //if only one condition was passed
                if (binaryExpr.Left is MemberExpression)
                {
                    expressionResult = CreateExpression(binaryExpr, parameter,binaryExpr.NodeType);

                }
                else if (binaryExpr.Left is BinaryExpression)
                {
                    var predicatesList = new List<BinaryExpression>();

                    var leftExp = CreateExpression((BinaryExpression)binaryExpr.Left, parameter, binaryExpr.Left.NodeType);
                    var RightExp = CreateExpression((BinaryExpression)binaryExpr.Right, parameter, binaryExpr.Right.NodeType);

                   expressionResult = Expression.And(leftExp, RightExp);


                }

                return Expression.Lambda<Func<TLinq, bool>>(expressionResult, parameter);
            }
            catch (Exception ex)
            {
                throw new Exception("Eror While creating Filter", ex);
            }

        }

        private static BinaryExpression CreateExpression(BinaryExpression expression, ParameterExpression parameter,ExpressionType expType)
        {

            var memberExp = expression.Left as MemberExpression;

            if (memberExp == null) throw new ArgumentException("left  expression is not a member Expression");

            //create the Member expression
            MemberExpression member = LambdaExpression.PropertyOrField(parameter, memberExp.Member.Name);

            //create the constant against the value
            ConstantExpression constant = Expression.Constant(((ConstantExpression)expression.Right).Value);


            return CreateExpressionOfType(expType, member, constant);


        }


        private static BinaryExpression CreateExpressionOfType(ExpressionType expType, MemberExpression member, ConstantExpression constant)
        {

            //creates the body fo the lambda 
            var resultExpression = default(BinaryExpression);
            switch (expType)
            {

                case ExpressionType.And:
                    break;
                case ExpressionType.AndAlso:
                    break;
                case ExpressionType.ConvertChecked:
                    break;
                case ExpressionType.Equal:
                    resultExpression = Expression.Equal(member, constant);
                    break;
                case ExpressionType.ExclusiveOr:
                    break;
                case ExpressionType.GreaterThan:
                    resultExpression = Expression.GreaterThan(member, constant);
                    break;
                case ExpressionType.GreaterThanOrEqual:
                    break;
                case ExpressionType.LessThan:
                    resultExpression = Expression.LessThan(member, constant);
                    break;
                case ExpressionType.LessThanOrEqual:
                    break;
                case ExpressionType.Not:
                    break;
                case ExpressionType.NotEqual:
                    break;
                default:
                    break;
            }

            return resultExpression;


        }


    }
like image 366
Oscar Cabrero Avatar asked Mar 26 '09 07:03

Oscar Cabrero


People also ask

What is parameter expression?

ParameterExpression. A ParameterExpression that has the NodeType property equal to Parameter and the Type and Name properties set to the specified values.


1 Answers

No, you can't change the type of a ParameterExpression (expression trees are immutable); you would have to rebuild the entire tree to do this. And yes, you often have to recurse it. Sorry...

like image 62
Marc Gravell Avatar answered Oct 15 '22 08:10

Marc Gravell