如何将通过反射获得的方法分配给委托? (或者:如何通过反射来加快方法调用的速度)

我知道已经有这样的问题,但是我真的很不明白答案(我似乎无法对此发表评论).

我对反思是完全陌生的,对于代表们也是陌生的,所以对我来说这很难.

前一段时间,我使用反射(第一次)来获得一个方法,我这样做是(简化的):

object perlinObj;
MethodInfo PerlinMethod = null;    
//...
ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
perlinObj = constructor.Invoke(new object[] { });
PerlinMethod = type.GetMethod("GetValue", new Type[] { typeof(Vector3) });
//...
float PerlinFunction(Vector3 pos)
{
   return (float)((Double)PerlinMethod.Invoke(perlinObj, new object[] { pos }));
}

这可行,但是问题是它比直接调用该方法慢得多.
所以我想,也许我可以以某种方式将其分配给一个委托,然后调用该委托而不是使用invoke,我认为这样会更快. (这是正确的?)

但是我找不到如何做到这一点.
我不了解msdn:http://msdn.microsoft.com/en-us/library/ms228976.aspx上的文档(我什至不确定它们是否与我尝试做的一样),
通过阅读以下内容,我也无法完全理解我要做什么:Assign method to delegate through reflection.

(我尝试过的没有用)

因此,有人可以向我解释我在提供的示例代码中必须做什么吗?

解决方法:

要以“简便”的方式进行操作,您需要比目标更准确地了解目标.即代替:

object perlinObj;

您将需要:

SomeType perlinObj;

然后,我们使用Delegate.CreateDelegate来创建委托,而不是存储MethodInfo-请注意,为了方便起见,我在这里使用int代替Vector3:

Func<SomeType, int, float> PerlinMethod;
//...
PerlinMethod = (Func<SomeType, int, float>) Delegate.CreateDelegate(
        typeof(Func<SomeType, int, float>),
        null,
        type.GetMethod("GetValue", new Type[] { typeof(int) }));
//...
float PerlinFunction(int pos)
{
    return PerlinMethod(perlinObj, pos);
}

请注意,如果目标实例永远不会改变,则可以简化:

Func<int, float> PerlinMethod;
//...
PerlinMethod = (Func<int, float>) Delegate.CreateDelegate(
        typeof(Func<int, float>),
        perlinObj,
        type.GetMethod("GetValue", new Type[] { typeof(int) }));
//...
float PerlinFunction(int pos)
{
    return PerlinMethod(pos);
}

如果您不能做到这一点,则有必要使用更高级的元编程. ILGenerator或Expression:

Func<object, int, float> PerlinMethod;
//...
var target = Expression.Parameter(typeof(object));
var arg = Expression.Parameter(typeof(int));
var call = Expression.Call(
    Expression.Convert(target, type),
    type.GetMethod("GetValue", new Type[] { typeof(int) }),
    arg);

PerlinMethod = Expression.Lambda<Func<object,int,float>>(
    call, target, arg).Compile();
上一篇:java-使用反射调用方法时传递的对象


下一篇:在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke