我最近一直在做很多关于DTO的阅读,以前从未使用过它们。我读过的一篇文章谈到了DTO不应该只复制域模型对象,而是应该根据正在执行的服务操作来定制每个DTO。
如果我决定使用DTO并想知道以下是否可以接受,这让我想到了验证?
public class Person {
public Guid Id {get; set;}
public string Name {get; set;}
public Address Address {get; set;}
}
public class Address {
public Guid Id {get; set;}
public string AddressLine1 {get;set;}
...
}
publuc class CreatePersonDTO {
private string _name;
private string _addressLine1;
public string Name {
get {
if (_name == null)
throw new Exception("Missing");
return _name;
}
set { _name = value; }
}
public string AddressLine1 {
get { return _addressLine1; }
set { _addressLine1 = value; }
}
}
因此,您将数据传递到Json或Xml中,并将其序列化为对象CreatePersonDTO,并在映射这些值以创建Person和Address对象时,如果缺少Persons Name,则会抛出验证异常。
由于DTO本身是特定于服务操作的,所以这里的验证是否可以,或者是否违反了关于业务逻辑应该驻留在哪里的某种规则?
答案 0 :(得分:4)
DTO应该没有验证;他们严格用于传输数据。除了验证之外,他们应该完全没有任何行为。
如果名称是必需的,那么这是域或给定服务操作的一个方面;验证应该封装在相应的位置(尽管您也可以在UI中强制执行规则以获得更好的体验)。
答案 1 :(得分:2)
我会解释每个DTO应根据正在执行的服务操作进行定制,以表示如果您有庞大的域对象,DTO可以表示与特定服务操作相关的子集。即它可能只对域对象的一些属性感兴趣。
答案 2 :(得分:1)
这取决于。但通常不是将验证登录到DTO的好地方。你会遇到可重用性问题。例如,如果您需要更新人员,则必须创建UpdatePersonDTO并将所有相同的逻辑放在那里。
作为另一种选择,您可以将验证逻辑放入Person本身,这样您就无法创建无效的人,并且它将是可重用的。或者您可以将实体验证逻辑放入某种服务层。
答案 3 :(得分:1)
您不应将验证逻辑放入DTO中,这应该主要由您的域层处理,在某些情况下,应该在您的UI层中重复。您的DTO应该就是那个,愚蠢的对象来传输数据。
除了责任分离之外,你的逻辑实际上不能被序列化。通过线路传输的唯一事物是值本身。如果您将此对象传递给非.NET使用者(例如,通过WCF),那么他们不一定会在对象中内置相同的规则,以便将数据反序列化为。