3

我最近一直在阅读有关 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 本身是特定于服务操作的,所以在这里进行此验证是否可以,或者它是否违反了某种关于业务逻辑应驻留在何处的规则?

4

4 回答 4

4

DTO 不应该有验证;它们严格用于传输数据。除了验证之外,它们应该真的没有任何行为。

如果需要名称,那是域或给定服务操作的一个方面;验证应该封装在相应的位置(尽管您也可以在 UI 中强制执行规则以获得更好的体验)。

于 2012-09-04T15:49:17.670 回答
2

我会解释每个 DTO 都应该针对正在执行的服务操作进行定制,这意味着如果您有庞大的域对象,DTO 可以表示与特定服务操作相关的子集。即它可能只对域对象的一些属性感兴趣。

于 2012-09-04T15:48:54.813 回答
1

那要看。但通常将验证登录放入 DTO 并不是一个好地方。您将遇到可重用性问题。例如,如果您需要更新人员,则必须创建 UpdatePersonDTO 并将所有相同的逻辑放在那里。
作为另一种选择,您可以将验证逻辑放入 Person 本身,这样您将无法创建无效的人员,并且可以重用。或者您可以将实体验证逻辑放入某种服务层。

于 2012-09-04T15:48:10.463 回答
1

您不应该将验证逻辑放入您的 DTO,这应该主要由您的域层处理,并且在某些情况下,在您的 UI 层中复制。您的 DTO 应该就是用于传输数据的哑对象。

除了这里的职责分离之外,您的逻辑实际上不能被序列化。唯一可以通过网络传输的是值本身。如果您将此对象传递给非 .NET 使用者(例如通过 WCF),那么他们不一定会在将数据反序列化到的对象中内置相同的规则。

于 2012-09-04T15:50:50.323 回答