我的代码是伪代码。 我想让这个函数可以接受一个Expresstion类型,编译这个表达式并用适当的参数调用它。
public static void f<T>(Expression<T> exp, params dynamic[] d)
{
Console.WriteLine("begin");
exp.Compile().Invoke(d[0],d[1].....);//this is pseudo-code
Console.WriteLine("end");
}
我确定T是Action类型。 (T可以是Action
,Action<int>
等。)。参数d
是一个动态类型的数组,它被发送到调用。
但我不知道如何完成代码。我确信这不容易实现。也许在c#
中不可能是真的答案 0 :(得分:3)
除非您知道确切的签名,否则无法使用Invoke
。但是,您可以使用DynamicInvoke
,例如:
((Delegate)exp.Compile()).DynamicInvoke(d);
请注意,上述dynamic
没有任何意义 - d
也可能是object[]
。
另一种稍微复杂的方法 - 将其编译为Func<object[]>
,并重写表达式(ExpressionVisitor
)以替换“参数n”(来自原始{{ 1}})exp
,其中p[n]
是单p
,ParameterExpression
是n
ConstantExpression
。这可能是有利的如果你要存储并积极地重新使用已编译的lambda。但是在您的特定方案中,您正在编译每次调用,因此这没有任何好处。
这是一个例子,但这主要是针对具有类似场景的后来读者,但是重新使用已编译的委托的情况;这种重写的“优势”在于,它保留了n
的性能影响,同时保留了Delegate.DynamicInvoke
的{{1}}签名;但这仅在代理被多次使用时才有用。目前(每次调用编译)这里的大部分“工作”将在表达式编译和JIT编译中。
object[] => object
答案 1 :(得分:2)
public static void F<T>(Expression<T> exp, params object[] d)
{
Console.WriteLine("begin");
var del = exp.Compile() as Delegate;
del.DynamicInvoke(d);
Console.WriteLine("end");
}
然后:
F<Action<int>>(i => Console.WriteLine(i), 5);
或:
F<Action<string, int>>((s, i) => Console.WriteLine("{0} : {1}", s, i), "Hello", 5);