DTO的。属性还是字段?

时间:2012-05-31 09:56:32

标签: c# wcf soa dto

我需要创建一些DTO类来跨WCF传输业务对象。

由于这些只是没有功能的数据包,有什么理由我不能只使用字段,还是有充分的理由将它们作为属性正确公开?

//fields
[DataContract]
class CustomerDTO
{
    [DataMember] public int     Id;
    [DataMember] public string  Name;
}

//or properties?
[DataContract]
class CustomerDTO
{
    [DataMember] public int    Id               { get; set; }
    [DataMember] public string Name             { get; set; }
}

6 个答案:

答案 0 :(得分:17)

如果我可以避免的话,我主要支持带有只读字段的不可变DTO:

public class CustomerDTO
{
    public CustomerDTO(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public readonly int     Id;
    public readonly string  Name;

    // Override Equals and GetHashCode as well...
}

不可变的记录具有很多优点,例如结构相等性,这使自动测试断言的编写更加容易。也dispenses with the need to write and maintain separate Test Data Builders

但这取决于序列化器。 JSON.NET可以处理不可变的记录,但许多其他序列化器则不能。

对于那些处理公共字段的人,我更喜欢字段而不是属性,这仅仅是因为它更诚实。 automatically implemented read/write properties provide no encapsulation

一些序列化程序坚持使用公共属性,而不序列化字段。如果是这种情况,则必须这样做。

老实说,考虑到我对此有多大的思考,这并不是让我彻夜难眠的东西,因为最终at the boundaries, applications aren't object-oriented。因此,OOD规则实际上并不真正适用于DTO。

答案 1 :(得分:4)

  

由于这些只是没有功能的数据包,我有什么理由不能只使用字段

这里没有针对公共领域的强烈论据。但是要意识到这只是因为DTO中没有逻辑(行为),因此封装的正常参数不成立。

我仍然会喜欢属性,但这里并不是必需的。

答案 2 :(得分:1)

DataMember属性将同时适用于公共字段和属性,因此任何一种都可以。但是,我建议坚持使用属性。

特别是,如果您使用的是StyleCop,那么您将会破坏rule SA1401

此规则存在的原因并不适用于您的情况,但如果您将StyleCop验证作为持续集成服务器上的构建的一部分运行,则仍然是一个维护问题。

答案 3 :(得分:1)

您可以使用其中之一。由于它不会影响性能,因此如果遇到某些序列化框架或与公共字段不兼容的类似框架,您将更安全地使用属性。

请注意,即使您在服务端使用公共字段,WCF代理生成也会在客户端使用公共属性及其支持私有字段创建这些DTO。如果您不希望这样,您需要在服务和客户端之间共享DTO库。

答案 4 :(得分:1)

与其他我没有看到的字段相比,这里的属性有两个优点。

  1. 语法中的摩擦与功能正确匹配

我认为默认行为应该是更安全的选择。对于字段,默认行为允许可变性,这是更危险的选择。必须添加关键字readonly以使字段不可变(在构造函数之外)。相反,auto属性的默认状态是不可变的。必须添加语法set;才能使属性可变(在构造函数之外)。

  1. Visual Studio's Code Lens中的引用计数

与字段不同,在Visual Studio中查看属性具有“代码镜头”,其中包括其引用计数。由于有了这些附加信息,我能够比字段更快地理解和重构属性。当然,可以使用Shift + F12在Visual Studio中搜索对诸如字段和属性之类的内容的引用,但这是一个额外的步骤,需要花费一些时间。此外,在极少数情况下,某些项目会包含多个目标。这将使Shift + F12搜索结果更难以使用,因为每个目标都进行了搜索。在合同中,物业的“代码镜片”中给出的参考计数与项目目标的数量无关。

结论

不过,为了直接回答问题,我更喜欢使用可变属性(并且没有显式构造函数),以确保我将使用序列化库中最幸福的快乐路径(在the answer of @ErenErsönmez中提到)

答案 5 :(得分:0)

我永远不会直接揭露领域,大多数公司都禁止在他们的标准中使用。实际上你完全扔掉了封装。 DTO是一种更复杂的东西的贫血表征,这是一个奇怪的例子,因为它们的属性无论如何都会破坏封装。就个人而言,我会使用这些属性,就像他们在那里一样。它还允许您实现“脏”功能等,如果您需要直接调整字段而不是那么容易。