2011-11-15 89 views
7

我想知道什么是设计DTO对象的构造函数的最佳做法。C#Dto构造函数和依赖注入

说,我有一个DTO对象是这样的:

class CustomerDto 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Phone { get; set; } 
    ... 
} 

有几种方法来构造对象:当你看到这

public CustomerDto(string name, string surname, string phone, ...) 
{ 
    this.Name = name; 
    this.Surname = surname; 
    this.Phone = phone; 
    ... 
} 

我可以声明构造构造函数并立即结束SRP(单个责任)违规?

即使这些属性都是相关的。

人们也可能会认为没有必要验证属性,因为这是一个DTO并且没有任何行为,行为应该位于此映射的域对象上。

在C#中,我们还可以更优雅的构造这个对象:

var dto = new CustomerDto() 
{ 
    Name = "Some name", 
    Surname = "Some surname" 
} 

或者用一口流利的建设者或如NBuilder的框架。

Automapper也有自动映射框架的用法。问题还在于使用Ioc容器,Ctor变得复杂,以及交换参数的风险,例如,如果您姓氏在哪里传递,反之亦然,验证可能会错过这个更容易,然后显式映射,如上所述。

请帮助说服我哪一种更好的方法。

+0

[依赖注入 - 使用数据传输对象(DTO)?](http:// stackoverflow。com/questions/6297322/dependency-injection-use-with-data-transfer-objects-dtos) –

+0

我遇到了同样的问题,并决定不使用构造函数。出于一个简单的原因:稍后,在一个月或6几个月,我或其他人会看这个,并且必须以我自己(和你自己)现在所想的方式思考它。我发现在阅读代码的过程中思考它太复杂了。 – dferraro

回答

10

您的示例中的值类型不是依赖关系。依赖性为消费者提供功能(或配置)。在你的情况下,它们只是分配给你的DTO的正常值。只要数据属于一起,即使在构造函数中分配了很多值,也不会违反SRP。这种情况下的唯一责任是保存数据。

另外DTO不应该由IoC容器创建,并且没有真正的依赖关系。您应该通过持久性框架或使用自动映射手动创建它们。

如果使用构造函数或属性分配值更好取决于使用情况。如果他们是必需的构造函数变种更好。如果他们是可选的财产方式更好。

+0

我喜欢这个答案,它确认了我对依赖关系的看法,而且这些并不是真正的依赖关系,它们不是您想让Ioc容器替代的外部子系统。另外,选项2的原因是它确实允许自动映射框架完成它的任务,它只是在边界之间传输数据。我确实认为dto需要说出一个名称的争论并不是它真正关心的问题?同意? – Andre

3

我建议使用不可变数据结构,以便DTO实体不会公开任何setter,显然这样构造函数应该提供初始化给定DTO的所有基础属性的能力。

所以我更喜欢:

public CustomerDto(string name, string surname, string phone, ...) 

DTO是数据传输对象,尤其是代表一组属性跨系统(分布式以及)边界传递,所以不要打扰太多关于SRP违反。 这就像Facade的设计模式,它突破了一组操作/服务以简化使用。所以在这个kase Keep It Simple赢了。

+1

我想知道的是Martin fowler将数据传输对象描述为一个保存状态并且没有行为的对象,并且实际上将它描述为一种减少方法调用的方法。通过引入构造函数参数并验证它们,您就添加了行为。请记住,目的是从域映射到视图,并且最有可能在域对象上进行验证。那么dto是否真的需要担心这些争论以及需要什么,因为它只是将数据携带到其他地方,而验证则是另一个问题? – Andre

+1

像'not null' /'not empty'这样的参数验证不是一个对象行为,认为它就像你的应用程序框架服务的东西。但是如果你打算像'if(customerRole == Roles.Vip)IncreaseBonus(x)'那样封装验证 - 这将是行为的确并且不应该在DTO本身中,DTO代表对象的最终satte – sll

+0

我刚刚测试过它看起来像Automapper是非常聪明的,它会将构造函数参数映射到属性。事情是,虽然我认为它取决于用法,如果你从一个域对象(已验证)映射到一个视图(验证)没有理由创建构造函数参数,它看起来像构造函数的方法没有缺点,但我可以看到一个大的。你不能立即发现一个论点是否是错误的方法,或者实际上是一个论点映射到的属性? – Andre