Dot-Net
從 MethodInfo 建構一個委託?
在Google搜尋並登陸 SO 並閱讀了另一個問題之後
如果您在編譯時不知道參數的數量或類型,是否可以從 MethodInfo 建構正確的委託?
更多資訊:不使用 Reflection.Emit 或 type builder 可以優雅地完成嗎?
這對我來說有點令人沮喪,因為 Delegate.CreateDelegate 要求我將正確的 Delegate 類型指定為第一個參數,否則它會引發異常或呼叫不正確的方法。
我正在製造一些忍者裝備,這將有很大幫助……謝謝!
這是一個通用的解決方案:
/// <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 介面。
需要支持所有這些遺留 JS 介面以及用於訪問新功能的新介面,因此自動設置 JS 介面並“委託”對正確 Silverlight 方法的呼叫將有助於大大加快工作速度。
我不能在這裡發布程式碼,所以這是摘要。
老實說,如果您在編譯時不知道類型,那麼創建
Delegate. 你不想使用DynamicInvoke; 它將與反射一樣慢。主要的例外是當有一個代理類型潛伏在陰影中時,例如在訂閱一個事件時 - 在這種情況下EventInfo,它可以使用。有關資訊,在 .NET 3.5 on 中
Expression,有:Expression.GetActionType(params Type[] typeArgs); Expression.GetFuncType(params Type[] typeArgs)這可能在一定程度上有所幫助:
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; } }