【问题标题】:How to get an Expression from a Lambda Expression如何从 Lambda 表达式中获取表达式
【发布时间】:2020-03-10 22:18:00
【问题描述】:

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

“PropertyName”“Operator”“PropertyValue”(例如:data.employee.salary = 10000)。这是针对一个将数据作为属性的主类运行的,该类实际上指向一个名为 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】:

这个问题有点令人困惑,但听起来你手头有三样东西:

  • 带有参数x 和主体x.i.p 的lambda 表达式lambda
  • 表达式value
  • 二元运算符类型 -- 假设它是“加法”。

而你想要的是为x =&gt; 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);

这有意义吗?

【讨论】:

  • 感谢您的快速回复。抱歉,这是一个冗长的问题。是的,我想我误会了错误线。你是绝对正确的,所以我将这一行改为 var binaryExpression = Expression.MakeBinary(rule.Operator, key.Body, value);但是我编译ExpTreeRules.Add...的下一行实际上是出错了。错误是:'System.Func'2 类型的表达式不能用于返回类型'System.Boolean'。
  • 当没有嵌套类时我有这行代码:var key = MemberExpression.Property(genericType, rule.PropertyName);,这行永远不会出错:compiledExpTreeRules.Add(Expression.Lambda >(key, genericType).Compile());​ 但是当我得到键时: var key = CreateExpression(typeof(T), rule.PropertyName);​,同一行抛出以上错误。
  • 我实际上正在努力格式化我上面的 cmets,使其可读。我正在输入两个空格,但没有换行。我很抱歉。
  • @Ram_P:SO cmets 中没有换行符,抱歉!你可以做的,让它稍微更具可读性是使用 "``" 反引号到 format code like this
  • 好的。谢谢:-)。 var key = MemberExpression.Property(genericType, rule.PropertyName); 后跟 ``compiledExpTreeRules.Add(Expression.Lambda>(key, genericType).Compile());​ 不会出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
相关资源
最近更新 更多