我需要处理一个由两个主要部分组成的应用程序:
通用部分使用反射从业务类中获取数据,而无需在业务类中编写特定的数据网格或数据库逻辑。这很好,允许我们添加新的业务类(例如LibraryMember),而无需调整数据网格和数据库逻辑。
然而,多年来,代码被添加到业务类中,这些业务类也使用反射来在业务类中完成工作。例如。如果一本书的作者被改变,观察者会被要求告诉作者本身它应该将这本书添加到他所写的书籍集(作者书)中。在这些观察者中,不仅传递实例,而且还传递直接从反射中得到的信息(FieldInfo被添加到观察者调用中,以便调用者知道书籍的“作者”字段被更改)。 p>
我可以清楚地看到在这些通用模块(如数据网格或数据库接口)中使用反射的优势,但在我看来,在业务类中使用反射是一个坏主意。毕竟,应用程序不应该尽可能不依赖于反射吗?或者反思是21世纪“正常的工作方式”?
在业务逻辑中使用反射是一种好习惯吗?
编辑:对Kirk的评论做了一些澄清:
答案 0 :(得分:9)
反射的主要危险在于,灵活性可能会升级为无组织的,无法维护的代码,特别是如果更多的初级开发人员用于进行更改,他们可能无法完全理解反射代码或者如此迷恋它们以至于他们使用它来解决所有问题,即使简单的工具就足够了。
我的观察是过度概括会导致过度复杂化。当实际边界情况不能被广义设计所适应时,情况会变得更糟,需要黑客按计划适应新功能,将灵活性转化为复杂性。
答案 1 :(得分:6)
我避免使用反射。是的,它使您的程序更灵活。但这种灵活性价格很高:没有编译时检查字段名称或类型,或者通过反射收集的任何信息。
与许多事情一样,这取决于你在做什么。如果你的逻辑的本质是你永远不会将找到的字段名称(或其他)与常量值进行比较,那么使用反射可能是一件好事。但是如果你使用反射来查找字段名称,然后遍历它们搜索名为“作者”和“标题”的字段,那么你刚刚创建了一个具有两个命名字段的对象的更复杂的模拟。如果您在字段实际上称为“AuthorName”时搜索“作者”,或者您打算搜索“作者”并意外键入“Auhtor”,该怎么办?现在,您遇到的错误在运行时才会显示,而不是在编译时被标记。
使用硬编码的字段名称,IDE可以告诉您每个地方使用某个字段。反思......不是那么容易辨别。也许您可以对名称进行文本搜索,但如果字段名称作为变量传递,则可能会非常困难。
我正在研究一个原始作者喜欢反思和类似技术的系统。他们需要创建一个类实例的各种地方,而不只是说“新”和类,他们创建一个令牌,他们在表中查找以获取类名。这有什么收获?是的,我们可以更改表格以将该令牌映射到其他名称。这让我们感到兴奋......什么?你最后一次说,“哦,我的程序创建一个Customer实例的每个地方,我想改变创建一个NewKindOfCustomer的实例。”如果您对某个课程进行了更改,则可以更改该课程,而不是创建一个新课程,但保留旧课程以保持怀旧。
为了解决类似的问题,我通过向数据库询问字段名称,类型和大小的列表,然后从那里进行布局,定期练习构建数据输入屏幕。这为我提供了为所有更简单的数据输入屏幕使用相同程序的优势 - 只需将表名作为参数传递 - 如果添加或删除字段,则需要更改零代码。但这只有在我不关心这些领域的情况下才有效。一旦我开始具有特定于该屏幕的验证或副作用,系统就会比它的价值更麻烦,我最好还是回到更明确的编码。
答案 2 :(得分:3)
我倾向于不使用反射,我可以帮助它。通过使用接口和编码来对付这些我可以做很多事情,有些人会使用反射。
但是,如果它有效,我是一个忠实的粉丝,它可行。
同样通过使用反射你可能有一些可以很容易适应的东西。
即大多数人唯一的反对意见是相当宗教......如果你的表现很好而且代码是可维护和清晰的......谁在乎呢?
编辑:基于你的编辑,我确实会使用接口来实现你想要的。除非我误解了你。
答案 3 :(得分:3)
根据您的编辑,听起来您使用反射纯粹作为识别字段的机制。这与动态行为相反,例如查找字段,应该尽可能避免(因为这样的查找通常使用破坏静态类型安全性的字符串)。使用FieldInfo
为字段提供标识符是相当无害的,尽管它确实以一种不完全理想的方式暴露了一些内部(信息类)。
答案 4 :(得分:2)
我认为尽可能远离Reflection是个好主意,但是当它为您的问题提供更好或更灵活的解决方案时,不要害怕诉诸它。在应用程序或Web表单请求的整体方案中,除了紧密循环操作之外的任何操作都可能是最小的。
分享关于反思的好文章 -
http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/
答案 5 :(得分:2)
我倾向于在业务层使用接口,并将反射留给我的表示层。这不是绝对的,而是一个指导原则。