当您设置属性的值时,您可以在更新内部值之前或之后进行验证。
如果之前验证,则在新值无效时可能会引发异常。 然后,对象始终处于有效状态。
如果之后验证,则需要撤消(即通过IEditableObject),以便用户可以随时取消编辑。 我们还可以选择在此处抛出异常或通过 IDataErrorInformation 公开错误。
我认为如果在设置之前进行验证,IDataErrorInfo 没有意义。有些人还可能争辩说,在验证方案中不需要抛出异常。
在自定义对象包含在 BindingList 中并设置为网格的数据源的情况下,验证效果很好。
之前验证也可以使用网格,但您必须抛出异常才能向数据网格发出属性值设置失败的信号(没有很多额外的代码)
我也对我的域对象实现IEditableObject和IDataErrorInfo,INotifyPropertyChanged等感到不舒服。 它使域对象充满额外的问题。 但是,如果您想很好地放置数据绑定,这似乎是不可避免的。 我可以创建一个包装器,也许是DTO,但我并不太疯狂地不得不编写大部分虚拟的额外代码来支持这些数据绑定位。
如何验证对象(最好是在数据绑定和 UI 的上下文中)?
请参阅我对业务对象、验证和异常的回答: 我认为Paul Stovell关于验证的想法(在本文中总结)非常强大。
通过在域实体(可能还有IEditableObject
和INotifyPropertyChanged
)中实现IDataErrorInfo
,可以使它们能够在许多.NET表示技术(Windows Forms,WPF,ASP .NET...)上进行数据绑定,而无需太多代码。或者您可以在脚本或批处理(即非 UI 流程)中使用它们,并且仍然可以根据业务规则验证它们:顺利(查询当前实体状态)或困难的方式(如果无效则在保存时抛出异常)。
最主要的是,使用这种模式,您的域实体负责自己的验证(这很好,当然在我看来不像额外的问题)。如果保存处于无效状态,他们通过在保存时抛出有意义的异常来强制执行它。它们可以很好地与您的代码(UI 或否)配合使用,如果您愿意先询问,请让您知道它们是否有效。
我甚至在我的软件工厂项目(仍处于早期阶段)中将这些原则应用于域模型之外:萨拉曼卡。