问题描述
|
假设我有一个描述域模型的Domain程序集,它有一个名为product的类:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
我还有另一个程序集,即使用此域模型运行的Web应用程序。现在,我想创建一个表单来创建新产品,并对属性进行一些验证。最简单的方法是在类上使用DataAnnotations。但是,这导致域模型现在包含有关表单验证的元数据,这并不是很明确的关注点分离。
可以为该类设置MetadataType
属性,但我认为这并不好。突然,您的域模型类依赖于表单验证Metada类。
另一种方法是创建一个“ 2”类并在其中添加所需的属性,并在这些类之间进行映射。但是,这会产生一些开销,因为您需要分别维护这些类,并且其中一个的更改可能会破坏另一个。在某些情况下可能需要这样做,但在另一些情况下,可能会创建额外的工作(例如,假设您有一个Address类)。
更新:有人建议我为此使用AutoMapper,我已经知道了。 AutoMapper只是使映射变得越来越容易,实际上并没有解决必须维护几乎相同的两个独立类的问题。我的偏好是仅在有特殊需要时才创建表单类。
是否可以在Web程序集中声明注释而又不为域程序集创建不必要的依赖关系呢?
解决方法
为什么您的域类上没有DataAnnotations。如果有某些要求,那么我认为在域中将其标记为必需是完全有效的。
其他DataAnnotation(例如StringLength,Range等)对我来说都是完全有效的东西,用来装饰您的域实体。
对于领域对象执行恕我直言,实现IValidableObject也是完全可以接受的事情。
我不会把UI东西放到上面,例如UIHint或描述属性格式的注释。那将是不好的。
通常,我避免在用户界面上显示域类,而将ViewModel类与映射工具(例如AutoMapper等)一起使用来相互映射。 ViewModel类具有域类的注释,可能还带有其他特定于UI的注释。
, 如果您不想在域模型和视图之间引入耦合,则应采用CreateProductForm类的方式。
根据您的项目规模/要求,您迟早需要将视图模型与域分开。假设您正在使用DisplayName属性:是否要标记域实体?
使用AutoMapper之类的工具可以大大简化映射过程。
, 在mathieu和XHalent状态下,您应将CreateProductForm(或CreateProductFormViewModel)与Automapper一起使用,并创建将模型自动映射到操作的ViewModel的属性。
这样,所有表单验证都将在视图模型中进行,而所有数据验证(与数据库有关)都将在域模型中进行。
在Silverlight和WPF中,它被称为MVVM模式,许多使用asp.net mvc的人都推荐它。
在我当前的项目中,我还将它与Automapper一起使用。我所有的视图都有一个关联的视图模型,该视图模型是特定于该视图的域模型的扁平版本。
我认为这是我使用的示例(无论如何,这是我仍然添加了书签的示例。但是,第一个链接的示例似乎更好。)
使用该属性意味着您可以从控制器中的操作中返回域对象,而automap属性则将域对象自动映射到您的viewmodel。
这样做应该为您提供所需的分隔。