尤其是对私人成员的反思是错误的
- 反射破坏了类型的安全性。您可以尝试调用一种不存在的方法(或不再存在),使用错误的参数,使用过多的参数,或者使用的方法不足够……甚至以错误的顺序(这是我最喜欢的:))。顺便说一句,返回类型也可以更改。
- 反射很慢。
私有成员反射破坏了封装原理,因此将您的代码暴露给以下对象:
- 增加代码的复杂性,因为它必须处理类的内部行为。隐藏的内容应保持隐藏状态。
- 使您的代码易于破坏,因为它可以编译,但如果方法更改了名称,将无法运行。
- 使私有代码易于破解,因为如果它是私有的,则不应以这种方式调用。也许私有方法在被调用之前期望内部状态。
如果我仍然必须这样做怎么办?
在某些情况下,当您依赖第三方或需要一些未公开的api时,必须进行一些反思。有些人还使用它来测试自己拥有的某些类,但是他们不想更改接口以仅出于测试目的而访问内部成员。
如果你这样做,那就正确
为了减轻容易中断的问题,最好的办法是通过在连续集成构建等中运行的单元测试中的测试来检测任何潜在的中断。当然,这意味着您始终使用相同的程序集(其中包含私有成员)。如果使用动态负载和反射,则喜欢玩火,但始终可以捕获该调用可能产生的异常。
在最新版本的.Net Framework中,CreateDelegate将MethodInfo调用的系数提高了50倍:
// The following should be done once since this does some reflection
var method = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
// Here we create a Func that targets the instance of type which has the
// Draw_ItemType method
var draw = (Func<TInput, Output[]>)_method.CreateDelegate(
typeof(Func<TInput, TOutput[]>), this);
draw
通话将围绕50倍的速度比MethodInfo.Invoke
使用draw
作为标准Func
像:
var res = draw(methodParams);
查看我的这篇文章以查看不同方法调用的基准