曾经与我一起工作并尊重的人曾对我说,在应用程序代码中不需要使用反射,它应该只在框架中使用。他说的是 J2EE 背景,而我在该平台的专业经验通常证明了这一点。尽管我曾经使用 Java 编写过一次或两次反射应用程序代码。
我对 Ruby on Rails 的体验完全不同,因为 Ruby 非常鼓励您编写动态代码。如果没有反射和元编程,Rails 为您提供的大部分功能根本不可能实现,并且许多相同的技术同样适用于您的应用程序代码并很有用。
- 您是否同意反射仅适用于框架的观点?我很想听听您的意见和经验。
曾经与我一起工作并尊重的人曾对我说,在应用程序代码中不需要使用反射,它应该只在框架中使用。他说的是 J2EE 背景,而我在该平台的专业经验通常证明了这一点。尽管我曾经使用 Java 编写过一次或两次反射应用程序代码。
我对 Ruby on Rails 的体验完全不同,因为 Ruby 非常鼓励您编写动态代码。如果没有反射和元编程,Rails 为您提供的大部分功能根本不可能实现,并且许多相同的技术同样适用于您的应用程序代码并很有用。
有一个老笑话,任何用静态类型语言编写的足够复杂的系统都包含一个不完整的、低劣的 Lisp 实现。
由于随着项目的发展,您的需求往往会变得更加复杂,因此您通常最终会发现静态类型对象系统中的常见习语最终会碰壁。有时寻求反思是最好的解决方案。
我对像 Ruby 这样的动态类型语言和像 C# 这样的静态类型语言很满意,但是 Ruby 中的隐式反射通常会使代码更简单、更容易阅读。(取决于所需的元编程魔法,有时更难编写)。
在 C# 中,我发现了不通过反射就无法解决的问题,因为直到运行时我才拥有信息。一个例子:当试图操作一些第三方代码生成代理到运行在另一个进程中的 Silverlight 对象时,我不得不使用反射来调用一个特定的强类型“通用”版本的方法,因为编组需要调用者假设其他进程中对象的类型是为了从中提取我们需要的数据,而 C# 不允许在运行时指定泛型方法调用的“类型”(反射除外技术)。我想你可能会说我们的工具是一种框架,但我可以很容易地想象一个普通应用程序中面临类似问题的案例。
反射使 DRY 更容易。当然可以编写没有反射的 DRY 代码,但它通常更冗长。
如果某些信息以一种方式编码在我的程序中,如果这是最简单的方法,我为什么不使用反射来获取它?
听起来他是在专门谈论 Java。在这种情况下,他只是引用了一个特例:在 Java 中,反射是如此的不稳定,它几乎从来都不是做某事的最简单方法。:-) 如您所见,在 Ruby 等其他语言中,通常是这样。
反射肯定在框架中大量使用,但如果使用得当,可以帮助简化应用程序中的代码。
我之前见过的一个例子是使用一个大型接口(20 多种方法)的 JDK 代理来包装(即委托给)一个特定的实现。使用 InvocationHandler 仅覆盖了几个方法,其余方法通过反射调用。
反射可能很有用,但它比执行常规方法调用要慢。请参阅此反射比较。
Java 中的反射通常不是必需的。这可能是解决某个问题的最快方法,但我宁愿解决导致您认为在应用程序代码中必要的潜在问题。我相信这一点,因为它经常将错误从编译时推到运行时,这对于足够大的软件来说总是一件坏事,以至于测试不是微不足道的。
我不同意,我的应用程序使用反射来动态创建提供程序。如果逻辑很简单并且不需要更复杂的模式,我也可以使用反射来控制逻辑流。
在 C# 中,我使用反射从枚举中获取属性,这有助于我确定如何向最终用户显示枚举。
我不同意,反射在应用程序代码中非常有用,我发现自己经常使用它。最近,我不得不使用反射仅从程序集的路径加载程序集(以调查其公共类型)。
这里表达了关于这个主题的几种观点......
没有其他方法时使用反射!这是性能问题!
如果您以前研究过 .NET 性能缺陷,那么正常反射的速度可能不会让您感到惊讶:重复访问 int 属性的简单测试证明,与直接访问属性相比,使用反射要慢约 1000 倍(比较测量时间的中位数 80% 的平均值)。
看到这个:.NET 反射 - 性能
MSDN 有一篇非常好的文章,关于何时应该使用反射?
如果您的问题最好通过使用反射来解决,那么您应该使用它。
(请注意,“最佳”的定义是从经验中学到的:)
框架与应用程序的定义也不是非黑即白。有时您的应用程序需要一些框架才能很好地完成工作。
我认为在应用程序代码中不需要使用反射并且它应该只在框架中使用的观察或多或少是正确的。
在某些代码的耦合程度方面,通过反射连接的代码与它们出现时一样松散耦合。
因此,通过反射完成它的工作的代码可以很高兴地完成它在生活中的作用,而对正在使用它的代码一无所知。