DTO形状:扁平,复杂/嵌套,或两者的混合

tbe*_*nin 21 c# asp.net-mvc domain-driven-design dto automapper

我有一个MVC2 n层应用程序(DAL,域,服务,MVC Web)使用DDD方法(域驱动设计),具有带存储库的域模型.我的服务层使用请求/响应模式,其中Request和Response对象包含DTO(数据传输对象)以将数据从一个层封送到下一个层,并且映射通过AutoMapper的帮助完成.我的问题是:DTO通常采用什么样的形状?它既可以嵌套/复杂的 DTO,还是严格来说是平面投影?或者可能两者兼而有之?另外,拥有平面DTO与更复杂/嵌套DTO的主要原因是什么?

例如,假设我有一个域,如下所示:

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Company Company { get; set; }
}
public class Company
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我有三种不同的方法可以对Response对象进行建模.

选项1 - DRYest选项:

public class GetEmployeeResponse
{
    public class EmployeeDTO { get; set; } // contains a CompanyDTO property
}
Run Code Online (Sandbox Code Playgroud)

根据我所做的研究,如上所示,DTO采用与域对象类似的形状是不合适的.

选项2 - 域的扁平投影(反DRY):

public class GetEmployeeResponse
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string CompanyName { get; set; }
    public string CompanyAddress { get; set; }
    public string CompanyCity { get; set; }
    public string CompanyState { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这更简单,就像DTO显然应该这样,但最终会产生更多的DTO.

选项3 - 两者的混合:

public class GetEmployeeResponse
{
    public EmployeeDTO Employee { get; set; }
    public CompanyDTO Company { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这允许代码更干燥,可重用和可管理,并且不会将我的域结构暴露给最终用户.另一个主要好处是其他响应,例如GetCompanyResponse可以简单地返回CompanyDTO,而不必复制所有这些属性,类似于选项2.你怎么看?您有哪些选择(如果有的话)和/或为您工作过?如果这些请求/响应稍后作为WCF服务方法公开,您的答案是否会改变?

Nat*_*her 12

我个人的偏好是尝试尽可能保持平坦,只传输所需的数据.说过去我曾经使用过深度嵌套的DTO,因为它在当时有意义且符合要求.所以我猜它归结为"它取决于".在一天结束时,请使用对手头的应用程序有意义的内容.没有必要尝试将喇叭数据转换为不符合您要达到的目标的DTO惯例.