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

时间:2013-10-23 11:01:20

标签: c# reflection delegates unity3d invoke

我知道已经有这样的问题了,但我真的不明白答案(我似乎无法对它们发表评论)。

我完全不喜欢反思,对代表来说也是新手,所以对我来说这很难。

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

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

(我试过的不起作用)

所以有人可以向我解释我在我提供的示例代码中要做什么吗?

1 个答案:

答案 0 :(得分:3)

要以“简单”的方式执行此操作,您需要比object更准确地了解目标;即代替:

object perlinObj;

你需要:

SomeType perlinObj;

然后,我们不是存储MethodInfo,而是使用Delegate.CreateDelegate来制作代理人 - 请注意我在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

如果你不能这样做,那么就有必要使用更高级的元编程; ExpressionFunc<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();

{{1}}