问题描述
谷歌搜索并登陆 SO 并阅读 this other question
After googling and landing on SO and having read this other question
是否可以从 MethodInfo 构建正确的委托如果您在编译时不知道参数的数量或类型?
Is it possible to build a correct Delegate from a MethodInfo if you didn't know the number or types of parameters at compile time?
关于此的更多信息:是否可以在不使用 Reflection.Emit 或类型生成器的情况下优雅地完成此操作?
More on this: can this be done elegantly without the use of Reflection.Emit or type builders?
这对我来说有点麻烦,因为 Delegate.CreateDelegate 要求我将正确的 Delegate 类型指定为第一个参数,否则它会引发异常或调用不正确的方法.
This is sorta a bummer for me because Delegate.CreateDelegate requires me to specify the correct Delegate type as the first parameter or else it would throw exceptions or invoke an incorrect method.
我正在制作一些忍者装备,这对我很有帮助...谢谢!
I'm building some ninja gears and this would helps a lot... Thanks!
这是一个通用的解决方案:
/// <summary>
/// Builds a Delegate instance from the supplied MethodInfo object and a target to invoke against.
/// </summary>
public static Delegate ToDelegate(MethodInfo mi, object target)
{
if (mi == null) throw new ArgumentNullException("mi");
Type delegateType;
var typeArgs = mi.GetParameters()
.Select(p => p.ParameterType)
.ToList();
// builds a delegate type
if (mi.ReturnType == typeof(void)) {
delegateType = Expression.GetActionType(typeArgs.ToArray());
} else {
typeArgs.Add(mi.ReturnType);
delegateType = Expression.GetFuncType(typeArgs.ToArray());
}
// creates a binded delegate if target is supplied
var result = (target == null)
? Delegate.CreateDelegate(delegateType, mi)
: Delegate.CreateDelegate(delegateType, target, mi);
return result;
}
<小时>
注意:我正在构建一个 Silverlight 应用程序,该应用程序将替换一个多年前构建的 javascript 应用程序,在该应用程序中,我有多个调用相同 Silverlight [ScriptableMember] 方法的 Javascript 接口.
Note: I am building a Silverlight application that would replace a built-years-ago javascript application in which I have multiple Javascript interfaces that calls into the same Silverlight [ScriptableMember] method.
需要支持所有这些遗留 JS 接口以及用于访问新功能的新接口,因此自动设置 JS 接口并将调用委托"到正确的 Silverlight 方法将有助于大大加快工作速度.
All those legacy JS interfaces need to be supported as well as new interface for accessing new features, so something that automatically setups the JS interface and "delegates" the call to the right Silverlight method would helps speed up work a lot.
我不能在这里发布代码,所以这是摘要.
I can't post code here, so that's the summary.
推荐答案
说实话,如果你在编译时不知道类型,那么创建一个Delegate代码>.你不想使用
DynamicInvoke
;它将与反射一样慢.主要的例外是当有一个代理类型潜伏在阴影中时,例如订阅一个事件时 - 在这种情况下 EventInfo
使其可用.
To be honest, if you don't know the type at compile time, there isn't a huge amount of benefit in creating a Delegate
. You don't want to use DynamicInvoke
; it will be about as slow as reflection. The main exception to this is when there is a delegate-type lurking in the shadows, for example when subscribing to an event - in which case EventInfo
makes this available.
有关信息,在 Expression
上的 .NET 3.5 中,有:
For info, in .NET 3.5 on Expression
, there is:
Expression.GetActionType(params Type[] typeArgs);
Expression.GetFuncType(params Type[] typeArgs)
这可能在一定程度上有所帮助:
That might help to an extent:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
static class Program {
static void Main() {
DoStuff("Test1");
DoStuff("Test2");
}
static void DoStuff(string methodName) {
MethodInfo method = typeof(Program).GetMethod(methodName);
List<Type> args = new List<Type>(
method.GetParameters().Select(p => p.ParameterType));
Type delegateType;
if (method.ReturnType == typeof(void)) {
delegateType = Expression.GetActionType(args.ToArray());
} else {
args.Add(method.ReturnType);
delegateType = Expression.GetFuncType(args.ToArray());
}
Delegate d = Delegate.CreateDelegate(delegateType, null, method);
Console.WriteLine(d);
}
public static void Test1(int i, DateTime when) { }
public static float Test2(string x) { return 0; }
}
这篇关于从 MethodInfo 构建一个委托?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!