如何使用 NRules 创建验证规则?

How to create a validation rule with NRules?

我刚刚发现了 .NET 的 NRules。如果 field/property 值无效,我想创建一个阻止对象构建的规则。例如,给定以下 class:

public class Customer
{
    public string Name { get; private set; }
    public bool IsPreferred { get; set; }

    public Customer(string name)
    {
        Name = name;
    }
}

我想要创建一个规则,当 'Name' 为 null 或空时会抛出异常,从而取消对象创建,并生成用户定义的消息:必须指定客户名称。

这可以用 NRules 来完成吗?如果可以,它是如何完成的?

使用 NRules,您可以根据特定领域或对象模型编写规则。所以你需要一些对象来保存数据,这样你就可以将这些对象插入到规则会话中,也可以将这些对象与规则进行匹配。 我想对于验证场景,您将使用以下之一:

  • 来自服务层的DTO
  • 表示层的 ViewModel 对象
  • Builder 对象在调用其 Build 方法之前(即 CustomerBuilder)
  • 域对象本身(构造它,然后验证并在无效时丢弃)

在更高的层次上,NRules 的最佳点是根据稳定的域模型来表达易变的业务逻辑。在这种情况下,您可以将验证逻辑分为两组 - 1) 稳定的验证并为域对象定义内在不变性,即客户名称不为空; 2) 易变的验证逻辑(即如果满足某些条件,客户是首选)。然后,您可以将类型 1 的验证逻辑编码为域模型本身中的断言,并将类型 2 的验证逻辑编码为这些域对象的规则。

无论采用哪种方式,在机械层面上,您可能希望验证规则为每个失败的验证插入一个 ValidationError,然后在结束时查询这些验证错误的会话并阻止对象构造(如果有的话)。

ObjectUnderValidation match = null;

When()
  .Match<ObjectUnderValidation>(() => match, x => x.ValidationCondition);

Then()
  .Do(ctx => ctx.Insert(new ValidationError(match, "Message")));

稍后进行验证时:

var session = factory.CreateSession();
session.Insert(myObjectUnderValidation);

session.Fire();
var errors = session.Query<ValidationError>().ToList();

if (errors.Any())
  //Don't construct
else
  //Construct

您还可以在此处抽象一些样板代码,使其更易于在您的特定场景中使用。