在wcf中,在属性
上应用DataMember
属性有什么区别
private int m_SomeValue;
[DataMember]
public int SomeValue {
get {...}
set {...}
}
而不是成员变量
[DataMember]
private int m_SomeValue;
public int SomeValue {
get {...}
set {...}
}
答案 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。
序列化 - 是持久化对象状态的过程。 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使用上述代码,则无法在客户端获取值。