使用数据注释和DDD“ChangeProperty”方法进行命令验证

时间:2015-07-09 22:35:17

标签: c# validation domain-driven-design data-annotations command-pattern

采用下面的简单实体......

public class MyEntity
{
    [MaxLength(100)]
    [Required]
    public string Name { get; private set; }
}

...是否可以读取正在装饰“Name”属性的数据注释并验证ChangeName方法中指定的值,以便ValidationResults可以连接到其他验证结果。我假设使用MethodInfo或PropertyInfo对象有些怎样?

我有这个,但感觉非常笨拙。

    public ValidationResult ChangeName(string value)
    {
        var property = GetType().GetProperty("Name");
        var attribute = property.GetCustomAttributes(typeof(MaxLengthAttribute), true)[0] as MaxLengthAttribute;
        if (attribute == null) return null; //yield break;

        if (value.Length > attribute.Length)
        {
            return new ValidationResult(NameValidation.NameTooLong);
        }

        return null;
    }

我希望能够从我的验证器中的方法调用ChangeName(value),就像这样..

    private IEnumerable<ValidationResult> ValidateMyEntity(MyEntityAddCommand command)
    {
        MyEntity myEntity = new MyEntity();
        yield return myEntity.ChangeName(command.Name);
    }

到目前为止我读到的大多数内容都说数据注释是针对CRUD而不是DDD,但为什么不使用它们,因为它们是描述验证行为的好方法,它将与我的MVC视图模型上的数据注释验证一致。 有没有更好或更简洁的方法可以做到这一点?所有建议都表示赞赏。

1 个答案:

答案 0 :(得分:6)

我不再追求验证可以(或应该)在一个地方发生的理想。在一个地方进行验证只是一个好主意,它删除了代码重复,但我没有遇到一个通用的问题(95%的工作原理)当时,但对于5%的情况,它不会花费你一天的开发来解决需要10分钟的事情。有时,验证规则可能会根据您使用的应用程序的视图或部分内容而有所不同。现在我验证数据进入我的系统,无论是网页表单还是网络服务等。我还通过拥有始终有效的域实体进行验证。

如果使用MVC,我将我的数据注释放在我的视图模型中。如果在ORM上使用(如EF或NHibernate),我将我的注释放在我的数据实体上,并将这些注释限制为被存储库隐藏(我的存储库返回域实体)。

我保持我的域实体不受验证类型注释(如果可能的话,任何注释)。我还确保我的域实体始终有效,并在尝试将我的实体设置为无效状态/值时抛出异常。通过这种方式,它向我发出错误的信号,而不仅仅是在验证意义上,但它告诉我,不正确的数据已经使它超越了我的第一道防线并且我需要修复我的代码。