如何在运行时计算表达式参数?

时间:2018-05-17 10:34:55

标签: c# expression expression-trees rule-engine dynamic-code

我需要解决的问题是通过IF语句运行数据。 IF语句由运行时的SQL表生成。

我已经设法通过使用表达式和Lambda表达式来实现这一点。

我的表有memberName;操作;目标。所以例如我从表中得到“Age”,“GreaterThan”和“40”,然后我编译它。

    var rule = new Rule(rowRule["memberName"].ToString(), rowRule["Operator"].ToString(), rowRule["Target"].ToString());

                Func<User, bool> compiledRule = CompileRule<User>(rule);  

我得到一个真或假值,它完美无缺。

     public static Func<T, bool> CompileRule<T>(Rule r)
    {
        var paramUser = Expression.Parameter(typeof(User));
        Expression expr = BuildExpr<T>(r, paramUser);
        // build a lambda function User->bool and compile it
        return Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile();
    }

     static Expression BuildExpr<T>(Rule r, ParameterExpression param)
    {
        var left = MemberExpression.Property(param, r.MemberName);
        var tProp = typeof(T).GetProperty(r.MemberName).PropertyType;
        ExpressionType tBinary;
        // is the operator a known .NET operator?
        if (ExpressionType.TryParse(r.Operator, out tBinary))
        {
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tProp));
            // use a binary operation, e.g. 'Equal' -> 'u.Age == 15'
            return Expression.MakeBinary(tBinary, left, right);
        }
        else
        {
            var method = tProp.GetMethod(r.Operator);
            var tParam = method.GetParameters()[0].ParameterType;
            var right = Expression.Constant(Convert.ChangeType(r.TargetValue, tParam));
            // use a method call, e.g. 'Contains' -> 'u.Tags.Contains(some_tag)'
            return Expression.Call(left, method, right);
        }
    }

这适用于简单的if语句,如“Age&gt; 30”

但现在我需要通过在if语句中嵌套计算来更复杂,例如我需要处理像“Age&gt;(30/2)”这样的语句

任何人都知道如何调整我的规则引擎以便能够进行计算。

如果我可以解析目标值,我从表中获取代码并在方法中执行并返回单个值然后创建规则,但我不确定如何在运行时获取字符串,解析代码并执行它。

我走下表达树的兔子洞,认为它可能是我的答案,但我已经意识到表达树只是一个可视化数据结构,而不是执行的代码。

如果像这样的某些规则引擎已经存在,它会很棒,但我还没有真正看到类似的东西。

0 个答案:

没有答案