我使用.Net语言已有4年了。我使用WCF,ASP.NET用于Web应用程序和C#用于Windows应用程序开发3层和5层应用程序。每次我开始一个项目时,业务规则和验证都是一个问题。
我应该在哪里放置自定义验证规则(按钮单击事件,页面加载或我的类中的setter / getter)?
如果项目很大并且只有一个字段而不是5个字符应该是7个字符 - 我为什么要重建整个项目(或业务类项目)?
我认为如果我有一个拥有自定义规则的文件,那么当需要进行更改时,我可以简单地在其中放置一条新规则。我已经在互联网上阅读了一些为此目的提供基于XML的文件的文章,但这似乎有问题,因为:
我的问题:
是否有使用.NET方法(反射,表达式树,Lambda表达式,动态,DLL的运行时创建等)的设计模式或其他任何东西,以使用自定义规则进行动态验证?
修改1)
属性怎么样?我们可以将它们与反射到自定义验证一起使用吗?我们可以使用这种方法根据另一个属性(形式示例P1应该是P2 + 1)来验证属性吗?
答案 0 :(得分:5)
表示业务规则的最佳方法是使用xml。要充分利用这种表示法,您应该首先定义规则引擎数据模型的结构,即回答这些问题。
完成此操作后,创建一个虚拟规则xml,然后根据此xml派生一个xml模式。 xsd.exe工具可以帮助您创建架构。如果您可以使用Altova XmlSpy等工具,则可以更轻松地创建架构。
至于具体问题的答案,
- 我们不能使用Intellisense,如果我们在XML文件中有错误,很难找到它。
一旦你有了架构,Visual Studio就会在创建xml时提供足够的支持(包括智能感知和验证)。
- 我们应该编写一个自定义的xml解析器
不需要,XmlSerializer Class提供序列化/反序列化的逻辑,即将规则xml转换为规则数据模型,反之亦然。
- 因为这种方法需要多次投射,所以非常慢
嗯,与硬编码规则(作为类嵌入到程序集中的规则)相比,这是一个部分有效的点,但这种方法的灵活性远远超过任何性能缺点。如果规则发生更改,则无需重建解决方案。在大多数情况下,性能影响很小。
除非您有严格的性能标准,否则xml方法是实现规则引擎的首选方法。请记住,架构越松散耦合,运行时的灵活性就越高,但对性能会产生负面影响。
示例规则
<RulesEngine>
<Rules>
<Rule Id="Rule1">
<Function>
<Equals>
<Property name="Property1" classId="MyClassId"/>
<Sum>
<Property name="Property2" classId="MyClassId"/>
<Constant type="UInt16" value="1"/>
</Sum>
</Equals>
</Function>
</Rule>
</Rules>
<Classes>
<Class name="MyNamespace.MyClass" Id="MyClassId">
<Property name="Property1" type="UInt16"/>
<Property name="Property2" type="UInt16"/>
</Class>
</Classes>
</RulesEngine>
规则引擎需要解释此规则并相应地推断其含义。
答案 1 :(得分:4)
看看FluentValidation。它使用表达式,您可以创建条件验证(例如,如果 符合某些条件,则验证这些属性)。 FV可能不是开箱即用的动态,但你获得了智能感知,表现力和类型安全。它的通用性意味着它运行得相当快。您可以通过传递验证委托或自定义验证器来注入一些运行时动态,这些验证委托可以执行您能想到的任何事情。
这确实意味着您必须重新编译,但您可以将验证器放在单独的程序集中。并且验证器不在类中/上是有意义的,因为您经常发现验证是在上下文中执行的。例如,如果汽车拥有所有车轮,则汽车可能有效。但是,如果你试图驾驶它并且它没有气体,那么它对驾驶来说是“无效的”。也就是说,我将这些规则定位为“接近”他们正在验证的内容,因为它们属于您的域名。