Dot-Net
.Net 3.5 中通過字元串名稱呼叫方法的最快方法是什麼?
所以顯而易見的方法是..
var handler = GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); handler.Invoke(this, new object[] {e});而且我可以添加記憶體以保留這些方法,但我想知道是否有完全不同且更快的方法?
最快的方法是記憶體一個類型化的委託;如果您知道簽名始終是:
void PersonInstance.MethodName(string s);
Action<Person,string>然後你可以通過 Delegate.CreateDelegate創建一個:var action = (Action<Person,string>)Delegate.CreateDelegate( typeof(Action<Person,string>), method);然後可以根據名稱記憶體它,並呼叫為:
action(personInstance, value);注意這裡的記憶體很關鍵;定位方法和準備類型委託的反思並非易事。
如果簽名是不可預測的,則變得更加困難,因為 DynamicInvoke 相對較慢。最快的方法是使用 DynamicMethod 和 ILGenerator 編寫一個接受對象的 shim 方法(動態)
$$ $$對於參數並解包並將其強制轉換以匹配簽名 - 然後您可以儲存
Action<object, object[]>orFunc<object,object[],object>。然而,這是一個高級主題。如果真的需要,我可以提供一個例子。本質上寫(在執行時):void DummyMethod(object target, object[] args) { ((Person)target).MethodName((int)args[0],(string)args[1]); }這是一個這樣做的例子(注意:它目前不處理
ref/outargs,可能還有其他一些場景 - 我已經將事物的“記憶體”方面作為練習留給讀者):using System; using System.Reflection; using System.Reflection.Emit; class Program { static void Main() { var method = typeof(Foo).GetMethod("Bar"); var func = Wrap(method); object[] args = { 123, "abc"}; var foo = new Foo(); object result = func(foo, args); } static Func<object, object[], object> Wrap(MethodInfo method) { var dm = new DynamicMethod(method.Name, typeof(object), new Type[] { typeof(object), typeof(object[]) }, method.DeclaringType, true); var il = dm.GetILGenerator(); if (!method.IsStatic) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Unbox_Any, method.DeclaringType); } var parameters = method.GetParameters(); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Unbox_Any, parameters[i].ParameterType); } il.EmitCall(method.IsStatic || method.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, method, null); if (method.ReturnType == null || method.ReturnType == typeof(void)) { il.Emit(OpCodes.Ldnull); } else if (method.ReturnType.IsValueType) { il.Emit(OpCodes.Box, method.ReturnType); } il.Emit(OpCodes.Ret); return (Func<object, object[], object>)dm.CreateDelegate(typeof(Func<object, object[], object>)); } } public class Foo { public string Bar(int x, string y) { return x + y; } }