使用数据注释和 DDD "ChangeProperty" 方法进行命令验证
Command validation using data annotations and DDD "ChangeProperty" methods
采用下面的简单实体...
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 视图上的数据注释验证一致模型。
有没有更好或更简洁的方法可以做到这一点?感谢所有建议。
我不再追求验证可以(或应该)在一个地方发生的理想。只在一个地方进行验证是一个好主意,它会消除代码重复,但我从来没有能够在不遇到一刀切的问题的情况下实现它(它在 95% 的时间里工作,但对于那 5% 的地方,它不需要花费你一天的开发时间来解决应该需要 10 分钟的事情)。有时,验证规则会根据您使用的应用程序的视图或部分而有所不同。现在我在数据进入我的系统时进行验证,无论是网页表单还是网络服务等。我还通过始终有效的域实体进行验证。
如果使用 MVC,我将我的数据注释放在我的视图模型中。如果在 ORM(如 EF 或 NHibernate)上使用,我将我的注释放在我的数据实体上并将它们限制为被存储库隐藏(我的存储库 return 域实体)。
我让我的域实体没有验证类型注释(如果可能,任何注释)。我还确保我的域实体始终有效,并在有人试图将我的实体设置为无效 state/value 时抛出异常。通过这种方式,它向我发出信号,表明出现了问题,不仅仅是在验证意义上,而且它告诉我,错误的数据以某种方式通过了我的第一道防线,我需要修复我的代码。
采用下面的简单实体...
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 视图上的数据注释验证一致模型。 有没有更好或更简洁的方法可以做到这一点?感谢所有建议。
我不再追求验证可以(或应该)在一个地方发生的理想。只在一个地方进行验证是一个好主意,它会消除代码重复,但我从来没有能够在不遇到一刀切的问题的情况下实现它(它在 95% 的时间里工作,但对于那 5% 的地方,它不需要花费你一天的开发时间来解决应该需要 10 分钟的事情)。有时,验证规则会根据您使用的应用程序的视图或部分而有所不同。现在我在数据进入我的系统时进行验证,无论是网页表单还是网络服务等。我还通过始终有效的域实体进行验证。
如果使用 MVC,我将我的数据注释放在我的视图模型中。如果在 ORM(如 EF 或 NHibernate)上使用,我将我的注释放在我的数据实体上并将它们限制为被存储库隐藏(我的存储库 return 域实体)。
我让我的域实体没有验证类型注释(如果可能,任何注释)。我还确保我的域实体始终有效,并在有人试图将我的实体设置为无效 state/value 时抛出异常。通过这种方式,它向我发出信号,表明出现了问题,不仅仅是在验证意义上,而且它告诉我,错误的数据以某种方式通过了我的第一道防线,我需要修复我的代码。