【发布时间】:2015-09-28 12:50:03
【问题描述】:
以下面的简单实体...
public class MyEntity
{
[MaxLength(100)]
[Required]
public string Name { get; private set; }
}
...是否可以读取装饰“名称”属性的数据注释并验证 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 视图模型上的数据注释验证一致。 有没有更好或更简洁的方法可以做到这一点?感谢所有建议。
【问题讨论】:
-
@plalx - 所以如果我的理解正确,我应该让我的实体的 ChangeName() 方法抛出一个验证异常,然后我的验证器可以捕捉到它并按照它的需要做?
-
这个想法是一个无效的命令应该几乎永远不会到达您的域。从这个意义上说,这是一种特殊情况,可以抛出异常。它不应该到达您的域,因为您将在 UI 上进行验证,在那里使用任何很棒的视图模型验证框架都是有意义的。最后,您最终会得到规则的重复,并且在某种程度上是这样,但 UI 通常会收集所有错误并将它们呈现给用户,而域应该尽早抛出并且不关心那个仪式。
-
在某些情况下,UI 可能无法执行验证,但这些通常更多的是关于命令本身的有效性而不是它的数据成员的有效性(例如,尝试在 5 分钟后修改评论关于 SO)。在这些情况下,我们希望命令能够到达域,我们必须确保返回描述性错误代码,让客户端能够了解发生了什么问题。
-
@plalx +1 表示“返回描述性错误代码”
标签: c# validation domain-driven-design data-annotations command-pattern