将动作转换为LambdaExpression

我正在使用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) => 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  ???
leemr66 回答:将动作转换为LambdaExpression

委托是指实际的已编译代码,而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;
,

在艰难地阅读了Holger的答案几个小时后,我想到了以下解决方案:

为了在运行时创建如下表达式:

Expression<Action<IContext,Model>> printExpression = (ctx,model) => model.AddCategory(5);

我已经制作了一个静态方法,可以根据需要生成一个动作:

public static Expression<Action<T,K>> GetActionExpression<T,K>(string methodName,int val)
{
    ParameterExpression ctx = Expression.Parameter(typeof(T),"ctx");
    ParameterExpression product = Expression.Parameter(typeof(K),"model");
    ParameterExpression actionMethodParam = Expression.Parameter(typeof(int),"val");

    var lambdaExpr = Expression.Lambda<Action<T,K>>(
        Expression.Call(
                  product,typeof(K).GetMethod(methodName,new Type[] { typeof(int) }),Expression.Constant(val)),new ParameterExpression[] {
                  ctx,product
              }
        );
        return lambdaExpr;
}

此方法生成如下表达式:

(ctx,模型)=>模型。{methodName}(val);

然后我通过反射调用此方法:

foreach(var item in actions) {

var actionMethodInfo = typeof(ExpressionBuilder).GetMethod("GetActionExpression")
                        .MakeGenericMethod(typeof(IContext),type);

                    LambdaExpression action = (LambdaExpression)actionMethodInfo.Invoke(null,new object[] {item.MethodName,item.Value });

}

就是这样。

本文链接:https://www.f2er.com/3058104.html

大家都在问