Crea una matrice di tutti i parametri ExpressionTree / Func

c# expression expression-trees lambda

Domanda

L'output del seguente programma è:

Primo: System.String. Secondo: System.String.

Il risultato atteso è: Primo: ciao1. Secondo: ciao2.

Se eseguo l'hardcode dell'indice su 1 o 2 in Expression.Assign (resultArrayAccessor, parameters [0]) funziona, ma ho bisogno di avere l'indice che segue la variabile i.

    public static void Main()
    {
        var type = typeof(Func<string, string, object>);
        var del = GenerateFunc<Func<string, string, object>>(type);
        del("hello1", "hello2");
        Console.ReadLine();
    }

    public static T GenerateFunc<T>(Type type)
    {
        var i = Expression.Parameter(typeof (int), "i");

        var x = type.GetMethod("Invoke");
        var target = typeof (Program).GetMethod("Target");

        var resultArray = Expression.Parameter(typeof(object[]), "result");
        var parameterArray = Expression.Parameter(typeof(ParameterExpression[]), "parameters");

        var resultArrayAccessor = Expression.ArrayAccess(resultArray, i);
        var parameterArrayAccessor = Expression.ArrayAccess(parameterArray, i);

        var label = Expression.Label();

        var parameters = x.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.ParameterType.ToString())).ToArray();

        var block = Expression.Block(x.ReturnType,
            new[] { resultArray, i, parameterArray },
            Expression.Assign(resultArray, Expression.Constant(new object[parameters.Length])),
            Expression.Assign(parameterArray, Expression.Constant(parameters)),
            Expression.Loop(
                Expression.Block(
                    Expression.IfThenElse(
                        Expression.LessThan(i, Expression.Constant(parameters.Length)),
                            Expression.Block(
                                Expression.Assign(resultArrayAccessor, parameterArrayAccessor),
                                Expression.PostIncrementAssign(i)
                            ),
                        Expression.Break(label)
                    )
                ),
                label
            ),

            Expression.Call(target, resultArray)
        );


        return Expression.Lambda<T>(block, parameters).Compile();
    }

    public static object Target(object[] test)
    {
        Console.WriteLine("First: " + test[0] + ". Second: " + test[1] + ".");
        return null;
    }

Risposta accettata

Finalmente capito, molto più semplice sintassi e funzionante;)

public static T GenerateFunc<T>(Type type)
{
    var target = typeof (Program).GetMethod("Target");

    var invokeMethod = type.GetMethod("Invoke");
    var parameters = invokeMethod
      .GetParameters()
      .Select(pi => Expression.Parameter(pi.ParameterType, pi.Name))
      .ToList();

    var parametersExpression = Expression.NewArrayInit(typeof(object), parameters);
    var body = Expression.Call(target, parametersExpression);
    return Expression.Lambda<T>(body, parameters).Compile();
}


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché