WCF:属性与成员上的DataMember属性

在wcf中,在属性上应用DataMember属性有什么区别

 private int m_SomeValue; [DataMember] public int SomeValue { get {...} set {...} } 

而不是一个成员variables

 [DataMember] private int m_SomeValue; public int SomeValue { get {...} set {...} } 

通常,您应该倾向于在属性上应用DataMember属性,而不是在专用字段上。 将该属性应用到字段的唯一原因是该属性是只读的(即它没有setter)。

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

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

但是,访问私有成员可能存在一些权限问题,特别是Silverlight和CF – 在这种情况下,我build议使用公有属性作为数据成员。 其实,除非我有一个很好的理由,否则我会倾向于总是使用财产。

您可能需要将字段而不是属性标记为DataMember,这是有很好的理由的。

请检查这个更多的细节: http : //blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

顺便说一下: 只有在完全信任环境中运行时, ContractSerializers才会序列化任何具有DataMemberAttribute的私有字段。 不能用于部分信任(请查看上面列出的博客以获取解决scheme)

这个决定取决于你使用WCF服务:

  1. 内部服务由您拥有的.NET系统共享相同的域模型。
  2. 不同平台消耗的外部服务,不共享相同的域模型。

情况1。

序列化 – 是坚持对象状态的过程。 C#中的对象的状态由其数据字段表示。

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

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

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

但大多数程序员都懒惰,他们喜欢用DataMemeber属性来简单地修饰Domain Entity。 在这种情况下,Field或Prop的决定取决于validation逻辑的位置,如果您的validation逻辑被隐藏在Set方法中,则必须使用Props,如果它是Extenral,则应使用Fields,并在Desirialization之后validationDomain Entity。

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

此外,我想提到Silverlight不能序列化\反序列化专用字段,因为您不能从外部使用reflection来访问它们,并且必须使它们变为专用并使用InternalsVisibleToAttribute。

案例2。

这很难。 这里主要关注的是互操作性。 在这种情况下,99.9%你将有单独的DTO类,最有可能是不同版本的DTO类来支持老客户。 在这里放入DataMembers属性并不重要,因为你使用了DTO。 我不打算解释这种情况,因为在这样大规模的系统上工作的开发人员通常是相当有经验的,而且他们也懒得读SO。

从理论上讲,只要你保持m_SomeValue总是等于m_SomeValue (就像一个简单的getter / setter),什么都没有。 除了由WCF公开的variables的名称。 (很显然,如果你给m_variables加上标签,那么你的代理类也会有相同的m_名称,无论你使用public / protected / internal / private字段还是属性,代理类都会生成一个公共属性。

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

就个人而言,我只是使用属性,并完全删除成员variables一起。 即

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

该属性将莫名其妙地在幕后创build一个成员variables。

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

[数据成员]
private int m_SomeValue;

public int SomeValue {get {…} set {…}}

如果你通过WCF使用它,上面的代码不能在客户端获得值。