Dot-Net

.Net 3.5 中通過字元串名稱呼叫方法的最快方法是什麼?

  • September 23, 2011

所以顯而易見的方法是..

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[]>or Func<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;
   }
}

引用自:https://stackoverflow.com/questions/7531297