3

次のプログラムの出力は次のとおりです。

最初: System.String。2 番目: System.String。

予想される結果は次のとおりです。最初: hello1。2 番目: hello2。

Expression.Assign(resultArrayAccessor, parameters[0]) でインデックスを 1 または 2 にハードコーディングすると機能しますが、変数 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;
    }
4

1 に答える 1

3

最後に、実際に機能するだけでなく、はるかに簡単な構文を理解しました;)

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();
}
于 2012-10-29T16:29:57.540 に答える