以下程序的输出是:
首先:System.String。第二:System.String。
预期结果是: 第一:hello1。第二:hello2。
如果我将索引硬编码为1或2 in Expression.Assign(resultArrayAccessor,parameters [0])它可以工作,但我需要在变量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;
}
答案 0 :(得分: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();
}