科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件对.NET Framework 反射的反思

对.NET Framework 反射的反思

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

在深入探究 System.Reflection 之前,我想先讨论一下一般的反射编程。

作者:lizhe1985 来源:天极Yesky软件频道 2007年11月2日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
动态调用代码

  迄今为止,我已经获得运行时对象的句柄(如类型和方法),仅作描述用,例如输出它们的名称。但是如何做得更多呢?如何实际调用某个方法呢?

  此例的几个要点是:首先,从一个 MyClass, mc1 实例检索一个 System.Type 实例,然后,从该类型检索一个 MethodInfo 实例。最后,当调用 MethodInfo 时,通过把它作为调用的第一个参数来传递,将其绑定到另一个 MyClass (mc2) 实例中。

  前面讲过,对于您预期在源代码中见到的类型和对象使用之间的区别,这个示例使这种区别变得模糊。逻辑上,您检索了一个方法的句柄,然后调用该方法,就象它属于一个不同的对象一样。对于熟悉函数式编程语言的程序员来说,这可能轻而易举;但对于只熟悉 C# 的程序员来说,要分离对象实现和对象实例化,可能就不是那么直观了。

  组合在一起

  至此我已经探讨过检查和调用的基本原理,接下来我会用具体的例子把它们组合在一起。设想您希望交付一个库,带有必须处理对象的静态帮助器函数。但在设计的时候,您对这些对象的类型没有任何概念!这要看函数调用方的指示,看他希望如何从这些对象中提取有意义的信息。函数将接受一个对象集合,和一个方法的字符串描述符。然后它将遍历该集合,调用每个对象的方法,用一些函数聚合返回值。

  就此例而言,我要声明一些约束条件。首先,字符串参数描述的方法(必须由每个对象的底层类型实现)不会接受任何参数,并将返回一个整数。代码将遍历对象集合,调用指定的方法,逐步计算出所有值的平均值。最后,因为这不是生产代码,在求和的时候我不用担心参数验证或整数溢出。

  在浏览示例代码时,可以看到主函数与静态帮助器 ComputeAverage 之间的协议除了对象自身的通用基类之外,并不依赖任何类型信息。换句话说,您可以彻底改变正在传送的对象的类型和结构,但只要总是能使用字符串描述一个方法,且该方法返回整数,ComputeAverage 就可以正常工作!

  需要注意的一个关键问题跟隐藏在最后这个例子中的 MethodInfo(一般反射)有关。注意,在 ComputeAverage 的 foreach 循环中,代码只从集合中的第一个对象中抓取一个 MethodInfo,然后绑定用于所有后续对象的调用。正如编码所示,它运行良好 — 这是 MethodInfo 缓存的一个简单例子。但此处有一个根本性的局限。MethodInfo 实例仅能由其检索对象同等层级类型的实例调用。因为传入了 IntReturner 和 SonOfIntReturner(继承自 IntReturner)的实例,才能这样运行。

  在示例代码中,已经包含了名为 EnemyOfIntReturner 的类,它实现了与其他两个类相同的基本协议,但并没有共享任何常见共享类型。换句话说,该接口逻辑上等同,但在类型层级上没有重叠。要探讨 MethodInfo 在该情形下的使用,请尝试向集合添加其他对象,通过“new EnemyOfIntReturner(10)”得到一个实例,再次运行示例。您会遇到一个异常,指出 MethodInfo 不能用于调用指定的对象,因为它和获得 MethodInfo 时的原始类型完全无关(即使方法名称和基本协议是等同的)。要使您的代码达到生产水准,您需要做好遇到这一情形的准备。

  一个可能的解决方案可以是通过自己分析所有传入对象的类型,保留对其共享的类型层级(如果有)的解释。如果下一对象的类型与任意已知类型层级相异,就需要获取和存储一个新的 MethodInfo。另一解决方案是捕获 TargetException,并重新获取一个 MethodInfo 实例。这里提到的两种解决方案都各有其优缺点。Joel Pobar 为本杂志 2007 五月期写过一篇优秀的文章,内容关于 MethodInfo 缓冲和我所极力推荐的反射性能。

  希望此示例演示的向应用程序或框架中添加反射,可以为日后的自定义或可扩展性增加更多的灵活性。不可否认,较之本机编程语言中的同等逻辑,使用反射可能会有些繁琐。如果您感到对您或您的客户来说,向代码中添加基于反射的后期绑定过于麻烦(毕竟他们需要以某种方式在您的框架中说明他们的类型和代码),那么可能仅需要适度的灵活性以取得某种平衡。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章