我一直在使用Func来创建
Expression.Lambda<Func<object, object>>(block, paramValues).Compile();
其中block是Expression.Block,用于创建所需的执行计划。 paramValues是Expression.Parameter值的数组:
var paramValues = epDef.Value.Parameters.Select(p => Expression.Parameter(typeof(object), p.Name))
.ToArray();
我试图修改它以接受一个数组,这样当我有超过16个输入参数时我可以使用Func:
Expression.Lambda<Func<object[], object>>(block, paramValues).Compile();
然而,这给了我以下错误:
Incorrect number of parameters supplied for lambda declaration
在这种情况下,有人可以帮助我使用Func接受16个以上的参数吗?使用数组作为输入或创建自定义委托
@MethodMan:
我试图在那个问题中实现解决方案,但我得到了同样的错误。根据我的理解,将Expression.Parameter从typeof(object)
更改为typeof(object[])
应该适用于我的情况,但我得到了相同的错误
编辑:
这是我从链接版本中尝试的修改版本:
class Program
{
static void Main(string[] argas)
{
Type[] types = new Type[] { typeof(object[]) };
var constructorInfo = typeof(Program).GetConstructor(types);
var parameters = types.Select((t, i) => Expression.Parameter(t, "p" + i)).ToArray();
var someType1Exp = Expression.New(constructorInfo, parameters);
var inner = Expression.Lambda(someType1Exp, parameters);
var args = Expression.Parameter(typeof(object[]), "args");
var body = Expression.Invoke(inner,
parameters.Select((p, i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), p.Type)).ToArray());
var outer = Expression.Lambda<Func<object[], object>>(body, args);
var func = outer.Compile();
object[] values = { 1, 123.45F, "abc" };
object obj = func(values);
Console.WriteLine(obj);
Console.WriteLine("test");
Console.ReadLine();
}
//public Program() { }
public Program(object[] values) { Console.WriteLine(values.ToString()); }
}
我收到以下错误:
System.InvalidCastException: 'Unable to cast object of type 'System.Int32' to type 'System.Object[]'.'
答案 0 :(得分:0)
你有问题是你改变你的lambda采用单个数组参数object[]
但是你仍然传递多个参数(paramValues
)。您需要传入一个值Array
。您还需要修改表达式主体以期望数组。
在你有相同的
之前考虑一下(a,b,c,d) => new Program(a, b, c, d)
现在你想要
(object[] a) => new Program((type0)a[0], (type1)a[1], (type2)a[2], (type3)a[3])
因此,您需要修改代码以直接引用参数数组的元素而不是参数:
class Program
{
static void Main(string[] argas)
{
var constructorInfo = typeof(Program).GetConstructors()[0];
var types = constructorInfo.GetParameters().Select(p => p.ParameterType);
var parm = Expression.Parameter(typeof(object[]), "args");
var parameters = types.Select((t, i) => Expression.Convert(Expression.ArrayIndex(parm, Expression.Constant(i)), t)).ToArray();
var someType1Exp = Expression.New(constructorInfo, parameters);
var outer = Expression.Lambda<Func<object[], object>>(someType1Exp, parm);
var func = outer.Compile();
object[] values = { 1, 123.45F, "abc" };
object obj = func(values);
Console.WriteLine(obj);
Console.WriteLine("test");
Console.ReadLine();
}
//public Program() { }
public Program(int val1, float val2, string val3) {
Console.WriteLine(val1);
Console.WriteLine(val2);
Console.WriteLine(val3);
}
}
如果要将object[]
传递给构造函数,如
(object[] args) => new Program(args)
你可以直接这样做(抱歉格式化,从我的LINQPad复制):
public class Program {
void Main() {
var constructorInfo = typeof(Program).GetConstructors()[0];
var parm = Expression.Parameter(typeof(object[]), "args");
var someType1Exp = Expression.New(constructorInfo, parm);
var outer = Expression.Lambda<Func<object[], object>>(someType1Exp, parm);
var func = outer.Compile();
object[] values = { 1, 123.45F, "abc" };
object obj = func(values);
Console.WriteLine(obj);
Console.WriteLine("test");
}
// Define other methods and classes here
public Program(object[] parms) {
Console.WriteLine(parms.ToString());
}
}