How to use lambda expression parameter in sub expression?

I would like to be able to create expressions like the following delegate:

Func<object[], object> createSomeType1 = (args) =>
{
    return new SomeType1((P1)args[0], (P2)args[1], (P3)args[2]);
};

I'm just starting with expressions in my hand, so excuse me if this is a pretty simple question (or I don’t understand something).

I know that to create a constructor with the correct types, I would do the following:

var p1 = Expression.Parameter(typeof(P1));
var p2 = Expression.Parameter(typeof(P2));
var p3 = Expression.Parameter(typeof(P3));
var someType1Exp = Expression.New(constructorInfo, p1, p2, p3);

And then I know that the “outer” lambda, I think, is declared as follows:

Expression<Func<object[], object>>.Lambda<Func<object[], object>>(
            someType1Exp,
            Expression.Parameter(typeof(object[])));

I am having problems with how to "pass" a parameter from an external expression to an internal expression, and then apply it to the correct type.

Any tips in the right direction are appreciated.

+3
source share
1 answer

iPod, : :

  • [] (Expression.Param(typeof(object[])))
  • , , , "Convert" "cast" (iPod again!),
  • Expression.Invoke, +

, ( )


:

Type[] types = new Type[] { typeof(int), typeof(float), typeof(string) };

var constructorInfo = typeof(SomeType).GetConstructor(types);
var parameters = types.Select((t,i) => Expression.Parameter(t, "p" + i)).ToArray();
var someType1Exp = Expression.New(constructorInfo, parameters);
var inner = Expression.Lambda(someType1Exp, parameters);

var args = Expression.Parameter(typeof(object[]), "args");          
var body = Expression.Invoke(inner,
    parameters.Select((p,i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), p.Type)).ToArray());
var outer = Expression.Lambda<Func<object[], object>>(body, args);
var func = outer.Compile();

object[] values = {1, 123.45F, "abc"};
object obj = func(values);
Console.WriteLine(obj);

:

Type[] types = new Type[] { typeof(int), typeof(float), typeof(string) };   
var constructorInfo = typeof(SomeType).GetConstructor(types);

var args = Expression.Parameter(typeof(object[]), "args");          
var body = Expression.New(constructorInfo,
    types.Select((t,i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), t)).ToArray());
var outer = Expression.Lambda<Func<object[], object>>(body, args);
var func = outer.Compile();

object[] values = {1, 123.45F, "abc"};
object obj = func(values);
Console.WriteLine(obj);
+2

Source: https://habr.com/ru/post/1773878/


All Articles