WCF:暴露只读的DataMember属性没有设置?
我有一个服务器端类,通过[DataContract]在客户端提供。 这个类有一个只读字段,我想通过一个属性提供。 然而,我无法这样做,因为似乎我没有被允许添加一个[DataMember]属性,而没有得到和设置。
所以 – 是否有一种方法来拥有一个[DataMember]属性而不需要setter?
[DataContract] class SomeClass { private readonly int _id; public SomeClass() { .. } [DataMember] public int Id { get { return _id; } } [DataMember] public string SomeString { get; set; } }
或者解决scheme将使用[DataMember]作为字段 – (如图所示)? 试图这样做,但它似乎并不在意字段是只读的?
编辑 :是唯一的方法来通过黑客这样做只读属性? (不 – 我不想这样做…)
[DataMember] public int Id { get { return _id; } private set { /* NOOP */ } }
你的“服务器端”类将不会被“提供”给客户端。
会发生什么:基于数据契约,客户端将从服务的XML模式创build一个新的单独的类。 它本身不能使用服务器端的类!
它将从XML模式定义中重新创build一个新类,但该模式不包含任何特定于.NET的东西,比如可见性或访问修饰符 – 毕竟它只是一个XML模式。 客户端类将以这种方式创build,使其在线上具有相同的“足迹” – 例如,它基本上序列化为相同的XML格式。
你不能通过一个标准的基于SOAP的服务“传输”.NET的特定知识 – 毕竟,你所传递的只是序列化的消息 – 没有任何类。
检查“SOA的四条原则”(由Microsoft的Don Box定义):
- 边界是明确的
- 服务是自治的
- 服务共享架构和合同,而不是类
- 可比性是基于政策
请参阅第3点 – 服务共享模式和合同, 而不是类 – 您只能共享数据协定的接口和XML模式 – 就是这样 – 没有.NET类。
将DataMember属性放在字段而不是属性上。
记住,WCF不知道封装。 封装是OOP术语,而不是SOA术语。
也就是说,请记住,对于使用你的课程的人来说,该字段是只读的,任何使用该服务的人都可以完全访问他们的字段。
我在服务层的一个类中有一些属性,我想把它传递给Silverlight。 我不想创build一个全新的class级。
不是真正的“推荐”,但是这似乎是将Total
属性传递给Silverlight(仅用于可视化数据绑定)的两个弊端中的一个。
public class PricingSummary { public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area public decimal SubTotal { get; set; } public decimal? Taxes { get; set; } public decimal Discount { get; set; } public decimal? ShippingTotal { get; set; } public decimal Total { get { return + SubTotal + (ShippingTotal ?? 0) + (Taxes ?? 0) - Discount; } set { throw new ApplicationException("Cannot be set"); } } }
有一种方法来实现这一点。 但要警告的是,它直接违反了这个答案中引用的以下原则:
“3.服务共享架构和合同,而不是阶级。”
如果这个违规行为不涉及你,这就是你所做的:
-
将服务和数据合约移动到单独的(便携式)类库中。 (让我们调用这个程序集
SomeService.Contracts
。)这是你如何定义一个不可变的[DataContract]
类:namespace SomeService.Contracts { [DataContract] public sealed class Foo { public Foo(int x) { this.x = x; } public int X { get { return x; } } [DataMember] // NB: applied to the backing field, not to the property! private readonly int x; } }
请注意,
[DataMember]
应用于后台字段,而不是相应的只读属性。 -
从您的服务应用程序项目(我将称为我的
SomeService.Web
)和您的客户端项目(我的称为SomeService.Client
)引用合同程序集。 这可能会导致您的解决scheme中的以下项目依赖关系: -
接下来,当您将服务引用添加到客户端项目时,请确保启用“重用types”选项,并确保您的合约程序集(
SomeService.Contracts
)将包含在SomeService.Contracts
:
瞧! Visual Studio不是从服务的WSDL模式中生成一个新的Foo
types,而是重用合约程序Foo
的不可变Foo
types。
最后一个警告:你已经偏离了其他答案中引用的服务原则。 但是尽量不要进一步stream浪。 您可能会开始尝试将(业务)逻辑添加到您的数据合同类中; 别。 它们应该尽可能地靠近你可以pipe理的哑数据传输对象(DTO)。
定义服务合同(接口)在使用该类实施合同之前。