2009-12-15 37 views
2

我有一个Windows WCF服务和Web客户端。我的服务有一个方法服务 - 客户端界面,架构建议

[OperationContract] 
SubmitOrder(OrderInfo info).... 

// class used to pass all relevant data 
[DataContract] 
class OrderInfo 
{ 
[DataMember] 
OrderType Type; 
// general order data 
} 

这是伟大的,直到我已经介绍了新的订单类型(由OrderInfo.Type属性控制)。您可以将新订单类型视为从一般订单派生(就行为而言)。 每个新订单都有一些附加属性。 实现Order的这种多态行为的最佳方法是什么?

目前我只是在添加新订单的同时向OrderInfo类添加新属性。

[DataContract] 
class OrderInfo 
{ 
[DataMember] 
OrderType Type; 
// general order data 

// First custom order data 
// Second custom order data 
// TODO - add new properties for new orders 
} 

我不喜欢它太多导致它太直。如果我更改了[DataContract]并且客户端 没有重建?

我的替代品是什么?我当然可以实现继承并衍生出新的[DataContract]类,如MyCustomOrder1,但继承不支持序列化,我需要使用由于某些原因被禁止的[KnownTypes]

+0

可能的重复:http://stackoverflow.com/questions/1826218/how-do-i-use-knowntype-to-enable-polymorphic-return-values-in-a-wcf-service-contr/1826321# 1826321 – 2009-12-15 13:56:45

+0

好吧,它不是重复的。我的问题是 - 如何在不使用[KnownTypes]的情况下用新属性扩展基类。 – 2009-12-15 14:12:12

+1

它是'KnownType',而不是'KnownTypes'。 – 2009-12-15 16:19:30

回答

5

关闭我的头顶,我不确定这是一个好主意,但我认为一种方法是放松服务方面的合同,例如,改用MessageContract并接受消息中的'any'内容。您仍然可以将您的数据合同分发给您的客户,因此您可以根据模型对客户进行编程。在服务方面,你需要弄清楚消息包含什么类型的内容并相应地采取行动。

我不知道如何实现这个细节,但我会看在WCF Message类开始:http://msdn.microsoft.com/en-us/library/ms734675.aspx

它归结为这里解释使用“类型化”的消息: http://geekswithblogs.net/claeyskurt/archive/2008/09/24/125430.aspx如以前这里讨论:(?也许更清洁)WCF and Anonymous Types


一个完全不同的方式做,这是使用IExtensibleDataObject在这个岗位http://geekswithblogs.net/claeyskurt/archive/2008/05/02/121848.aspx的第2部分解释。


编辑:我正在阅读有关data contract versioning,我认为这可能是一个更好的解决方案

如果因任何原因,你不能使用KnownType,你在做什么归结为创建新版本的合同。开始最简单的方法是将

  • 创建亚型
  • 添加一个“类型”属性的所有属性的单一OrderInfo的合同(字符串,因为你不能只是增加新的枚举之后,这将是一个重大更改)
  • 作出这样的选择的是“必需的”
  • 做出了对所有属性的基类的所有属性的亚型“可选”
  • 实施IExtensibleDataObject是向前兼容
  • 在我们的服务,请使用type属性,以确定它是什么样的秩序和采取相应的行动

现在,当你添加新的类型,添加新的特性到订单信息类,只要他们是可选的,并且班级的其他成员不会改变,您可以向后兼容尚未拥有合同新版本的客户。是的,它可能会在客户端变得混乱,但你总是可以将它抽象到一些辅助类的后面。

3

我需要使用[KnownType],它是 由于某些原因被禁止。

你是什么意思禁止?我没有任何问题使用KnownTypeAttribute。这是一个例子。

[DataContract] 
[KnownType(typeof(NetworkDeviceProperties))] 
public class DeviceProperties 
{ 
    [DataMember] 
    public string MachineName { get; set; } 
} 

[DataContract] 
public class NetworkDeviceProperties : DeviceProperties 
{ 
    [DataMember] 
    public IPAddress IPAddress { get; set; } 
} 

[ServiceContract] 
public interface ICollectionService 
{ 
    [OperationContract] 
    [ServiceKnownType(typeof(NetworkDeviceProperties))] 
    void Start(DeviceProperties properties); 
} 

在我的客户端,我创建了一个NetworkDeviceProperties对象,并没有问题传递给start()方法。有关更多信息,请参阅此blog