如何从Lambda表达式中获取表达式

问题描述 投票:-1回答:1

我正在开发一个规则引擎,其中使用这种设计在数据库中设置规则:

“ PropertyName”“操作员”“ PropertyValue”(例如:data.employee.salary = 10000)。这是针对以数据为属性的主类运行的,该主类实际上指向嵌套类Data,而“ data”内部类又具有称为employee的属性,该属性映射到Employee内部类,该内部类的属性为现在是字符串的薪水。

这是我使用ExpressionTrees编码的RulesEngine代码的一部分:

    // Loop through each of the rules per Ruleset and compile them against the properties of the supplied T object.
            //NOTE: The values in the database column 'PropertyName' should match exactly with the properties of the T class. ​
            rules.ForEach(rule =>​
            {​
                var genericType = Expression.Parameter(typeof(T));​
              //  var key = MemberExpression.Property(genericType, rule.PropertyName);​
                var key = CreateExpression(typeof(T), rule.PropertyName);​ //rule.PropertyName== 'data.employee.salary' 
                var propertyType = GetProp(typeof(T), rule.PropertyName).PropertyType;      // System.String          ​
                ​
                var value = Expression.Constant(Convert.ChangeType(rule.PropertyValue, propertyType));​ //"10000"
​`               if (rule.Operator != ExpressionType.Lambda && rule.Operator != ExpressionType.Default) //This covers both '=' and '<>' or anything Binary-ish Operators setup in the Rules table.​
                {​
                    var binaryExpression = Expression.MakeBinary(rule.Operator, key, value);​
                    compiledExpTreeRules.Add(Expression.Lambda<Func<T, bool>>(key, genericType).Compile());​
                }​

            static LambdaExpression CreateExpression(Type type, string propertyName)
            {​
                    var param = Expression.Parameter(type, "x");​
                    Expression body = param;​
                    foreach (var member in propertyName.Split('.'))​
                    {​
                        body = Expression.PropertyOrField(body, member);​
                    }​
                    return Expression.Lambda(body, param);​
            //return MemberExpression.Property(body, propertyName);​
        }

我遇到的问题是我从CreateExpression()方法返回了Expression.Lambda。我必须编写此方法,因为T输入类在其中具有嵌套类,因此可以在数据库中最内部嵌套类的叶子属性级别上配置属性和规则。

当我尝试执行此行时,它给我一个错误:

var binaryExpression = Expression.MakeBinary(rule.Operator, key, value);

当我已经知道Lambda表达式(即“ key”参数)时,如何制作二进制表达式? MakeBinary参数列表中的键错误。我也尝试过key.body,但我只是不知道如何1)使CreateExpression()返回MemberExpression.Property或2)当它返回类型为x => x.innnerclass1.prop1的lambda表达式时,我该如何用它作为“键”并进行BinaryExpression吗?我有lambda,我有运算符(来自db),并且我有值,但是我正在努力用它来构建BinaryExpression。

提前感谢!

c# linq expression-trees rules
1个回答
1
投票

这个问题有点令人困惑,但听起来您手上有三件事:

  • 带有参数lambda和主体x的lambda表达式x.i.p
  • 表达式value
  • 一种二进制运算符,假设它是“加法”。

并且您想要的是为x => x.i.p + value构造lambda,对吗?

要做的就是你说的>

// Given values:
LambdaExpression lambda = whatever;
Expression value = whatever;    
ExpressionType operator = whatever;
// Computed values:
Expression key = lambda.Body;
List<ParameterExpression> ps = lambda.Parameters;
BinaryExpression binop = Expression.MakeBinary(operator, key, value);
LambdaExpression newLambda = Expression.Lambda(binop, ps);

这有意义吗?

© www.soinside.com 2019 - 2024. All rights reserved.