我正在使用 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);
”。我认为唯一的方法是使用反射。因为我正在从数据库中读取一些值。
我可以使用反射生成 Action :
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 ???
最佳答案
委托(delegate)指的是真正的编译代码,而 Lambda 表达式是一个表达式树,接近源代码,只是不是文本形式。你可以调用你的委托(delegate),但别无他法。从 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;
关于c# - 将 Action 转换为 LambdaExpression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58975116/