Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Action to LambdaExpression

I am using NRules and trying to load rules from database.

For that, I have to use reflection to generate an Expression.

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);

My goal is to generate "Expression<Action<IContext, Product>> action = (ctx, product) => product.AddCategory(25);" on runtime. I think the only way to do this to use reflection. Because I am reading some values from database.

I could generate the Action by using reflection:

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

But NRules method is expecting a LambdaExpression as a parameter.

How can I convert "actionFromReflection" to LambdaExpression?

LambdaExpression le = actionFromReflection  ???
like image 962
fkucuk Avatar asked Apr 25 '26 23:04

fkucuk


1 Answers

A delegate refers to real compiled Code, while a Lambda Expression is an Expression Tree, close to Source-Code, just not in Text-Form. You can Call your Delegate, but nothing else. Creating Source-Code from IL-Code would be a job for a Disassembler.

Using Reflection means "Use something already compiled", that is the opposite of creating it at runtime. So this is the wrong approach.

To create a LambdaExpression at runtime you do something like

        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 })

Actually this sample does build ctx => ctx +1 If you have no return value, you probably have an Expression.Call. You have to further investigate, how to express what you want, as an expression Tree. That's a broad topic.

The LambdaExpression you can just cast:

var expr = (Expression<Action<ctx, product>>) lambdaExpr;
like image 155
Holger Avatar answered Apr 27 '26 14:04

Holger