.NET中的验证框架,可以在字段之间进行编辑

Jef*_*ron 4 .net c# validation validationrules

根据我的经验,.NET中的许多验证框架允许您一次验证一个字段,例如确保字段是邮政编码或电子邮件地址.我通常将这些内部编辑称为.

在我的项目中,我们经常需要进行场间编辑.例如,如果您有这样的类:

public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您可能希望确保Max大于Min.您可能还想对外部对象进行一些验证.例如,鉴于你有一个这样的类:

public class Person
{
    public string PostalCode { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因,您希望确保邮政编码存在于数据库或提供给您的文件中.我有更复杂的例子,比如用户提供数据字典,你想根据该数据字典验证你的对象.

我的问题是:我们可以使用任何现有的验证框架(TNValidate,NHibernate Validator)用于.NET,还是我们需要使用规则引擎或者什么?现实世界中的人们如何处理这种情况?:-)

Ste*_*ven 6

我只知道一个验证框架,即Enterprise Library Validation Application Block,简称VAB.我将从VAB的背景中回答您的问题.

第一个问题:你能在VAB中进行状态(场间)验证吗?

是的你可以.有多种方法可以做到这一点.您可以选择自我验证机制,如下所示:

[HasSelfValidation]
public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }

    [SelfValidation]
    public void ValidateRange(ValidationResults results)
    {
        if (this.Max < this.Min)
        {
            results.AddResult(
                new ValidationResult("Max less than min", this, "", "", null));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我必须说我个人不喜欢这种类型的验证,特别是在验证我的域实体时,因为我喜欢将验证与验证逻辑分开(并保持我的域逻辑不受任何验证框架的引用).但是,它们需要的代码比替代方案少得多,后者正在编写自定义验证器类.这是一个例子:

[ConfigurationElementType(typeof(CustomValidatorData))]
public sealed class RangeValidator : Validator
{
    public RangeValidator(NameValueCollection attributes)
        : base(string.Empty, string.Empty) { }

    protected override string DefaultMessageTemplate
    {
        get { throw new NotImplementedException(); }
    }

    protected override void DoValidate(object objectToValidate,
        object currentTarget, string key, ValidationResults results)
    {
        Range range = (Range)currentTarget;

        if (range.Max < range.Min)
        {
            this.LogValidationResult(results,
                "Max less than min", currentTarget, key);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编写此类后,您可以在验证配置文件中挂起此类,如下所示:

<validation>
  <type name="Range" defaultRuleset="Default" assemblyName="[Range Assembly]">
    <ruleset name="Default">
      <validator type="[Namespace].RangeValidator, [Validator Assembly]"
        name="Range Validator" />
    </ruleset>
  </type>
</validation> 
Run Code Online (Sandbox Code Playgroud)

第二个问题:如何通过数据库(使用VAB)进行复杂的验证.

我给第一个问题的例子也可用于此.您可以使用相同的技术:自我验证和自定义验证器.您想要检查数据库中的值的方案实际上很简单,因为对象的有效性不是基于其上下文.您只需根据数据库检查对象的状态即可.当对象生存的上下文变得重要时(但VAB可以实现),它会变得更加复杂.想象一下,例如,您想要编写一个验证,确保每个客户在给定的时间点不超过两个未发货的订单.这不仅意味着您必须检查数据库,而且可能在同一上下文中删除添加的新订单或订单.此问题不是VAB特定的,您选择的每个框架都会遇到同样的问题.我写了一篇文章,描述了我们在这些情况下面临的复杂性(阅读和颤抖).

第三个问题:现实世界中的人们如何处理这种情况?

我在生产代码中使用VAB进行这些类型的验证.它工作得很好,但VAB不是很容易学习.尽管如此,我喜欢用VAB做的事情,而且只有在v5.0发布时它才会变得更好.如果您想学习它,请先阅读您可以在动手实验室下载中找到的ValidationHOL.pdf文档.

我希望这有帮助.