尤其是对私人成员的反思是错误的
- 反射破坏了类型安全。您可以尝试调用一个不存在的方法(不再存在),或者使用错误的参数,或者使用太多参数,或者不够......甚至是错误的顺序(这是我最喜欢的:))。顺便说一句,返回类型也可以改变。
- 反射很慢。
私有成员反射破坏了封装原则,从而将您的代码暴露给以下内容:
- 增加代码的复杂性,因为它必须处理类的内部行为。隐藏的东西应该保持隐藏。
- 使您的代码易于破解,因为它可以编译,但如果方法更改其名称则不会运行。
- 使私有代码易于破解,因为如果它是私有的,则不打算以这种方式调用它。也许私有方法在被调用之前需要一些内部状态。
如果我必须这样做怎么办?
有这样的情况,当你依赖第三方或者你需要一些不暴露的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
调用将比MethodInfo.Invoke
使用draw
这样的标准快约 50 倍Func
:
var res = draw(methodParams);
检查我的这篇文章以查看不同方法调用的基准