我正在使用NRules,并尝试从数据库加载规则。

为此,我必须使用反射来生成表达式。

public class Product
{
     public string Attribute1 { get; }
     public List<int> Category { get; set; }
     public void AddCategory (int category){
          this.Category.Add(category);
     }
}




using NRules.RuleModel;
using NRules.RuleModel.Builders;

var builder = new RuleBuilder();
//some logic for buildin lefthand side
Expression<Action<IContext, Product>> action = (ctx, product) => product.AddCategory(25);
builder.RightHandSide().Action(action);


我的目标是在运行时生成“ Expression<Action<IContext, Product>> action = (ctx, product) => product.AddCategory(25);”。我认为使用反射的唯一方法是反射。因为我正在从数据库中读取一些值。

我可以使用反射来生成动作:

Type actionType = typeof(Action<>).MakeGenericType(new Type[] { typeof(IContext),
Type.GetType(actualModelName) });
MethodInfo eventMethodInfo = type.GetMethod("AddCategory");
Action actionFromReflection  = (Action)Delegate.CreateDelegate(actionType, eventMethodInfo);


但是NRules方法期望使用LambdaExpression作为参数。

如何将“ actionFromReflection”转换为LambdaExpression?

LambdaExpression le = actionFromReflection  ???

最佳答案

委托引用实际的已编译代码,而Lambda表达式是与源代码接近的表达式树,只是不是文本形式。您可以呼叫您的代表,但没有别的。从IL代码创建源代码将是反汇编程序的工作。

使用反射意味着“使用已经编译的东西”,这与在运行时创建它相反。因此,这是错误的方法。

要在运行时创建LambdaExpression,您可以执行以下操作

        ParameterExpression ctx = Expression.Parameter(typeof(Context), "ctx");
        ParameterExpression product = Expression.Parameter(typeof(Product), "product");

        LambdaExpression lambdaExpr = Expression.Lambda(
            /* your actual code, depending on what you want to do */
                Expression.Add(
                ctx,
                Expression.Constant(1)
            ),
            new List<ParameterExpression>() { ctx, product })


实际上,此示例确实构建了ctx => ctx +1
如果没有返回值,则可能有一个Expression.Call。
您需要进一步研究如何将您想要的内容表达为表达树。这是一个广泛的话题。

您可以投放的LambdaExpression:

var expr = (Expression<Action<ctx, product>>) lambdaExpr;

09-25 17:42