什么是最快的方法在.NET 3.5中调用一个方法,通过字符串名称? [英] What is the fastest way in .Net 3.5 to call a method by string name?

查看:164
本文介绍了什么是最快的方法在.NET 3.5中调用一个方法,通过字符串名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以明显的方式来做到这一点。

So the obvious way to do this is..

var handler = GetType().GetMethod(methodName, BindingFlags.NonPublic |
                                              BindingFlags.Instance);

handler.Invoke(this, new object[] {e});

我还可以添加缓存,保持周围的方法,但我不知道是否有一个完全不同的,更快捷的方式?

And I can add caching to keep the methods around but I'm wondering if there is a completely different and faster way?

推荐答案

的最快方法是将缓存类型的代表;如果您知道签名永远是:

The fastest way would be to cache a typed delegate; if you know the signature is always:

void PersonInstance.MethodName(string s);

然后,您可以创建一个动作<人,串> 通过Delegate.CreateDelegate:

Then you could create an Action<Person,string> via Delegate.CreateDelegate:

var action = (Action<Person,string>)Delegate.CreateDelegate(
    typeof(Action<Person,string>), method);

这然后可缓存针对名称,并且调用

This can then be cached against the name, and invoked as:

action(personInstance, value);

请注意,这里的缓存是关键的;反射来定位的方法和prepare一个类型化的代表是不平凡的。

Note that the cache here is critical; the reflection to locate the method and prepare a typed-delegate is non-trivial.

它变得更难,如果签名是联合国predictable,因为DynamicInvoke是比较慢的。在最快的办法是使用DynamicMethod的和的ILGenerator写一个垫片的方法(飞),这需要一个Object []为参数,然后解压缩,并蒙上它相匹配的签名 - 那么你可以存储一个动作&LT;对象,对象[] GT; Func键&LT;对象,对象[],对象&gt; 。即,然而,先进的主题。我可以提供一个例子,如果真的需要。从本质上写(在运行时):

It gets harder if the signature is unpredictable, as DynamicInvoke is relatively slow. The fastest way would be to use DynamicMethod and ILGenerator to write a shim method (on the fly) that takes an object[] for the parameters and unpacks and casts it to match the signature - then you can store an Action<object, object[]> or Func<object,object[],object>. That is, however, an advanced topic. I could provide an example if really needed. Essentially writing (at runtime):

void DummyMethod(object target, object[] args) {
    ((Person)target).MethodName((int)args[0],(string)args[1]);
}

下面是这样做的(注的例子:它不会在目前处理 REF / 退出的args ,并有可能其他一些情景 - 我已经离开了事物的缓存的一面作为练习读者):

Here's an example of doing that (note: it doesn't handle ref/out args at the moment, and possibly a few other scenarios - and I've left the "cache" side of things as an exercise for the reader):

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;
    }
}

这篇关于什么是最快的方法在.NET 3.5中调用一个方法,通过字符串名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆