在业务逻辑中使用reflection是一种好习惯吗?

我需要处理一个由两个主要部分组成的应用程序:

  • 具有特定业务类的业务逻辑部分(例如,书籍,库,作者……)
  • 可以在数据网格中显示Books,Libraries,…的通用部件,将它们映射到数据库,……)。

通用部分使用reflection从业务类中获取数据,而无需在业务类中编写特定的数据网格或数据库逻辑。 这很好,允许我们添加新的业务类(例如LibraryMember),而无需调整数据网格和数据库逻辑。

但是,多年来,代码被添加到业务类中,这些业务类还使用reflection来在业务类中完成工作。 例如,如果书籍的作者被更改,观察者会被要求告诉作者本身它应该将这本书添加到他所写的书籍集(Author.Books)中。 在这些观察者中,不仅传递实例,而且还传递直接从reflection得到的信息(FieldInfo被添加到观察者调用,以便调用者知道书的字段“作者”被更改)。

我可以清楚地看到在这些通用模块(如数据网格或数据库接口)中使用reflection的优势,但在我看来,在业务类中使用reflection是一个坏主意。 毕竟,应用程序不应该尽可能不依赖于reflection吗? 或者反思是否是21世纪“正常的工作方式”?

在业务逻辑中使用reflection是一种好习惯吗?

编辑 :关于Kirk的评论的一些澄清:

  • 想象一下,作者在Book上实现了一个观察者。
  • 只要书籍的某些字段发生变化(如标题,年份,#页面,作者……),书籍就会调用所有观察者。 更改字段的“FieldInfo”在观察者中传递。
  • 然后,作者 – 观察者使用此FieldInfo来决定是否对此更改感兴趣。 在这种情况下,如果FieldInfo用于Book of Book的作者,则Author-Observer将更新其自己的Books向量。

我避免使用reflection。 是的,它使您的程序更灵活。 但这种灵活性价格很高:没有编译时检查字段名称或类型或通过reflection收集的任何信息。

像许多事情一样,这取决于你在做什么。 如果你的逻辑的本质是你永远不会将找到的字段名称(或其他)与常量值进行比较,那么使用reflection可能是一件好事。 但是,如果您使用reflection来查找字段名称,然后循环搜索名为“作者”和“标题”的字段,那么您刚刚创建了一个具有两个命名字段的对象的更复杂模拟。 如果您在字段实际上称为“AuthorName”时搜索“作者”,或者您打算搜索“作者”并意外键入“Auhtor”,该怎么办? 现在,您遇到的错误在运行时才会显示,而不是在编译时被标记。

使用硬编码的字段名称,IDE可以告诉您每个地方使用某个字段。 反思……不那么容易辨别。 也许你可以对名称进行文本搜索,但如果字段名称作为变量传递,则可能会变得非常困难。

我正在研究一个原始作者喜欢reflection和类似技术的系统。 他们需要创建一个类实例的各种地方,而不只是说“新”和类,他们创建一个令牌,他们在表中查找以获取类名。 这有什么收获? 是的,我们可以更改表格以将该令牌映射到其他名称。 这让我们感到兴奋……什么? 你最后一次说,“哦,我的程序创建一个Customer实例的每个地方,我想改变以创建一个NewKindOfCustomer的实例。” 如果您对某个课程进行了更改,则可以更改该课程,而不是创建一个新课程,而是保留旧课程以保持怀旧。

为了解决类似的问题,我通过向数据库询问字段名称,类型和大小的列表,然后从那里进行布局,定期实现数据输入屏幕的构建。 这使我可以在所有更简单的数据输入屏幕上使用相同的程序 – 只需将表名称作为参数传递 – 如果添加或删除字段,则需要更改零代码。 但这只有在我不关心这些领域的情况下才有效。 一旦我开始具有特定于该屏幕的validation或副作用,系统就会比它的价值更麻烦,我最好回到更明确的编码。

反思的主要危险在于,灵活性可能会升级为无组织的,无法维护的代码,特别是如果更多的初级开发人员用于进行更改,他们可能无法完全理解reflection代码或者如此迷恋它们,以至于他们用它来解决每个问题即使简单的工具就足够了。

我的观察是过度泛化会导致过度复杂化。 当实际边界情况变得无法被广义设计所适应时,它变得更糟,需要黑客按计划适应新function,将灵活性转化为复杂性。

根据您的编辑,听起来您使用reflection纯粹作为识别字段的机制。 这与动态行为相反,例如查找字段,应该尽可能避免(因为这样的查找通常使用破坏静态类型安全性的字符串)。 使用FieldInfoFieldInfo提供标识符是相当无害的,尽管它确实以一种不完全理想的方式暴露了一些内部(信息类)。

我倾向于不使用reflection,我可以帮助它。 通过使用接口和编码对这些我可以做很多事情,有些人会使用reflection。

但是,如果它有效,我就是它的忠实粉丝。

同样通过使用reflection,你可能有一些可以很容易适应的东西。

即大多数人唯一的反对意见是相当宗教……如果你的表现很好而且代码是可维护和清晰的……谁在乎?

编辑:基于你的编辑,我确实会使用接口来实现你想要的。 除非我误解了你。

我认为尽可能远离Reflection是一个好主意,但是当它为您的问题提供更好或更灵活的解决方案时,不要害怕诉诸它。 在应用程序或Web窗体请求的整体方案中,除了紧密循环操作之外的任何操作都可能是最小的。

只是一篇分享反思的好文章 –

http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/

我倾向于在业务层中使用接口,并将reflection留给我的表示层。 这不是绝对的,而是一个指导原则。