Créer un tableau de tous les paramètres ExpressionTree / Func

c# expression expression-trees lambda

Question

La sortie du programme suivant est:

Premièrement: System.String. Deuxièmement: System.String.

Le résultat attendu est le suivant: hello1. Deuxièmement: bonjour2.

Si i code l'index à 1 ou 2 dans Expression.Assign (resultArrayAccessor, parameters [0]), cela fonctionne, mais j'ai besoin que l'index suive la variable 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;
    }

Réponse acceptée

Enfin compris, syntaxe beaucoup plus facile et fonctionne réellement;)

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


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow