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定义):

  1. 边界是明确的
  2. 服务是自治的
  3. 服务共享架构和合同,而不是类
  4. 可比性是基于政策

请参阅第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.服务共享架构和合同,而不是阶级。”

如果这个违规行为不涉及你,这就是你所做的:

  1. 将服务和数据合约移动到单独的(便携式)类库中。 (让我们调用这个程序集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]应用于后台字段,而不是相应的只读属性。

  2. 从您的服务应用程序项目(我将称为我的SomeService.Web )和您的客户端项目(我的称为SomeService.Client )引用合同程序集。 这可能会导致您的解决scheme中的以下项目依赖关系:

    在解决方案资源管理器中高亮显示项目依赖项

  3. 接下来,当您将服务引用添加到客户端项目时,请确保启用“重用types”选项,并确保您的合约程序集( SomeService.Contracts )将包含在SomeService.Contracts

    屏幕截图突出显示相关的服务参考设置

瞧! Visual Studio不是从服务的WSDL模式中生成一个新的Footypes,而是重用合约程序Foo的不可变Footypes。

最后一个警告:你已经偏离了其他答案中引用的服务原则。 但是尽量不要进一步stream浪。 您可能会开始尝试将(业务)逻辑添加到您的数据合同类中; 别。 它们应该尽可能地靠近你可以pipe理的哑数据传输对象(DTO)。

定义服务合同(接口)在使用该类实施合同之前。