以下程序的输出是:
第一个:System.String。第二:System.String。
预期的结果是:第一:hello1。第二:你好2。
如果我在 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;
}