Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Dto构造函数和依赖注入_C#_Design Patterns_Dependency Injection - Fatal编程技术网

C#Dto构造函数和依赖注入

C#Dto构造函数和依赖注入,c#,design-patterns,dependency-injection,C#,Design Patterns,Dependency Injection,我想知道设计DTO对象构造函数的最佳实践是什么 假设我有这样一个Dto对象: class CustomerDto { public string Name { get; set; } public string Surname { get; set; } public string Phone { get; set; } ... } 有几种方法可以构造对象: 我可以声明一个构造函数: public CustomerDto(string name, string

我想知道设计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"
}
或者使用fluent builder或NBuilder等框架

还可以使用自动映射框架,如Automapper。问题还在于使用Ioc容器—ctor变得复杂,以及交换参数的风险—例如,您在姓氏所在的位置传入名称,或者反之亦然—验证可能会错过上述比显式映射更简单的映射


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

我建议使用不可变的数据结构,这样DTO实体就不会公开任何setter,显然,通过这种方式,构造函数应该能够初始化给定DTO的所有底层属性

所以我更喜欢:

public CustomerDto(string name, string surname, string phone, ...) 
DTO是一个数据传输对象,特别是用来表示要跨系统(也分布式)边界传递的一组属性,所以不要太在意冲突。
这类似于Facade设计模式,它包含一组操作/服务以简化使用。因此,在本例中,kase-won.

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

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


如果使用构造函数或属性指定值更好,则取决于使用情况。如果需要,则构造函数变量更好。如果它们是可选的,那么属性方式更好。

我想知道的是Martin fowler将data trasnfer对象描述为一个保存状态而没有行为的对象,并将其描述为一种减少方法调用的方式。通过引入构造函数参数并对其进行验证,可以添加行为。请记住,其目的是从域映射到视图,验证很可能发生在域对象上。因此,DTO真的需要担心参数和需要什么,因为它只是简单地将数据携带到其他地方,验证是不同的关注点。参数验证,如<代码> NULL> <代码> >代码>不是空不是对象行为,将其视为您的应用程序框架服务的东西。但是,如果您要封装验证,比如
if(customerRole==Roles.Vip)IncreaseBonus(x)
——这确实是一种行为,不应该出现在DTO本身中,DTO表示刚刚测试的对象的最终状态,看起来Automapper非常聪明,它会将构造函数参数名称映射到属性。问题是,虽然在我看来这取决于使用情况,但如果您从一个域对象(已经验证)映射到一个视图(验证),那么就没有理由创建构造函数参数,看起来构造函数方法没有缺点,但我可以看到一个大缺点。如果一个参数是错误的,或者事实上一个参数映射到什么属性,你不能立即发现。我喜欢这个答案的原因是它证实了我对依赖性的看法,并且这些不是真正的依赖性,它们不是你想要一个Ioc容器来替代的外部子系统。选择2的另一个原因是,它确实允许自动映射框架完成它的工作—它只是在边界之间传输数据。我确实觉得dto要求说出一个名称参数的问题并不是它真正关心的问题?同意吗?可能是重复的我遇到了同样的问题,决定反对建造商。。原因很简单:一个月后,或者6个月后,我自己或者其他人会看到这一点,并且必须以我(和你自己)现在的思维方式来思考。我发现阅读代码时思考表明代码太复杂了。