WCF:属性与成员的DataMember属性

时间:2009-02-17 13:26:39

标签: .net wcf serialization

在wcf中,在属性

上应用DataMember属性有什么区别
private int m_SomeValue;

[DataMember]  
public int SomeValue {
  get {...}
  set {...}
}

而不是成员变量

[DataMember]  
private int m_SomeValue;

public int SomeValue {
  get {...}
  set {...}
}

7 个答案:

答案 0 :(得分:41)

通常,您应该支持在属性上应用DataMember属性,而不是在私有字段上应用。将该属性应用于该字段的唯一原因是该属性是否为只读(即它没有setter)。

答案 1 :(得分:24)

只要您使用Name标记,无论是使用字段还是属性,合同都是相同的。

[DataMember(Name="SomeValue")]
private int m_SomeValue;

但是,访问私有成员可能存在一些权限问题,特别是在Silverlight和CF上 - 在这种情况下,我建议使用公共属性作为数据成员。实际上,除非我有充分的理由,否则我倾向于总是使用财产......

答案 2 :(得分:6)

您可能希望将字段而不是属性标记为DataMember。

请查看此内容以获取更多详情:http://blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

顺便说一句:ContractSerializers将序列化任何具有DataMemberAttribute的私有字段仅在完全信任环境中运行。不能部分信任(请查看上面列出的博客以获得解决方案)

答案 3 :(得分:4)

此决定取决于您使用WCF服务:

  1. 您自己的.NET系统消耗的内部服务,它们共享相同的域模型。
  2. 不同平台消耗的外部服务,不共享相同的域模型。
  3. 案例1。

    序列化 - 是持久化对象状态的过程。 C#中对象的状态由它的数据字段表示。

    C#中的属性本质上是 - 操纵对象状态的方法。使用它们可能导致反序列化的不同对象状态,因为设置属性的顺序可能会影响它的最终数据状态。其他因素也可能导致不正确的状态反序列化,例如,方法(属性集)依赖于某些正在更改的上下文,如当前的DateTime。

    您可以说封装怎么样?我不希望我的对象处于无效状态,我必须进行验证检查,对象图完整性检查等。是的,你应该,所以我们将DataMember attribs放在道具上?没有。

    这里的问题是,很多人将两种不同的东西,DTO(数据传输对象,WCF合同)与域实体混合在一起。您需要的是确保您收到的数据与发送的数据完全相同,然后确保您可以从此数据构建有效的域实体。实现此目的的最佳方法是为DTO使用单独的类,并从中构建域实体。

    但大多数程序员都很懒,他们喜欢用DataMemeber属性简单地装饰Domain Entity。在这种情况下,决策字段或提议取决于验证逻辑的位置,如果验证逻辑隐藏在Set方法中,则必须使用Props,如果它是extenral,则应使用Fields,并验证域实体在绝望之后。

    P.S。我认为相同的规则适用于任何序列化过程,例如数据库持久性。

    另外,我想提一下Silverlight不能序列化\反序列化私有字段,因为你无法使用反射从外部访问它们,你必须将它们设为私有并使用InternalsVisibleToAttribute。 / p>

    案例2。

    这很难。这里的主要焦点是互操作性。在99.9%的情况下,在这种情况下,您将拥有单独的DTO课程,并且很可能很多不同版本的DTO课程都支持旧客户。将DataMembers归于此处并不重要,因为您使用的是DTO。我不打算解释这种情况,因为在这种大规模系统上工作的开发人员通常都很有经验,而且他们不会费心阅读SO。

答案 4 :(得分:3)

理论上,只要你让m_SomeValue始终等于SomeValue(就像一个简单的getter / setter),什么都没有。除了WCF公开的变量的名称。 (显然,如果您标记m_变量,那么您的代理类也将具有相同的m_名称。无论您使用public / protected / internal / private字段,代理类都将生成公共属性或财产。

但是,如果您的访问器中有任何特殊逻辑可能会修改返回的值(例如ToUpper()字符串),那么您将返回不同的值。

答案 5 :(得分:2)

就个人而言,我只会使用该属性并完全删除成员变量。即。

[DataMember]
public int SomeValue
{ get; set; }

该属性将在幕后莫名其妙地创建一个成员变量。

答案 6 :(得分:1)

如果在private int m_SomeValue上添加[DataMember],则该成员不能序列化,因此必须将其添加到public int SomeValue。

[DataMember]  
private int m_SomeValue;

public int SomeValue {
  get {...}
  set {...}
}

如果您通过WCF使用上述代码,则无法在客户端获取值。