Sha*_*lle 7 .net performance .net-3.5
所以明显的方法是......
var handler = GetType().GetMethod(methodName, BindingFlags.NonPublic |
BindingFlags.Instance);
handler.Invoke(this, new object[] {e});
Run Code Online (Sandbox Code Playgroud)
我可以添加缓存以保持方法,但我想知道是否有一个完全不同和更快的方式?
Mar*_*ell 15
最快的方法是缓存一个类型化的委托; 如果你知道签名总是:
void PersonInstance.MethodName(string s);
Run Code Online (Sandbox Code Playgroud)
然后你可以创建一个Action<Person,string>via Delegate.CreateDelegate:
var action = (Action<Person,string>)Delegate.CreateDelegate(
typeof(Action<Person,string>), method);
Run Code Online (Sandbox Code Playgroud)
然后可以根据名称缓存它,并调用为:
action(personInstance, value);
Run Code Online (Sandbox Code Playgroud)
请注意,此处的缓存至关重要; 定位方法和准备类型委托的反射是非常重要的.
如果签名不可预测会变得更难,因为DynamicInvoke相对较慢.在最快的方式是使用DynamicMethod的和的ILGenerator写一个垫片的方法(飞),其采用对象[]为参数,解包且将其相匹配的签名-那么你可以存储Action<object, object[]>或Func<object,object[],object>.然而,这是一个高级主题.如果确实需要,我可以提供一个例子.基本上写(在运行时):
void DummyMethod(object target, object[] args) {
((Person)target).MethodName((int)args[0],(string)args[1]);
}
Run Code Online (Sandbox Code Playgroud)
这是一个这样做的例子(注意:它目前不处理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;
}
}
Run Code Online (Sandbox Code Playgroud)