2012-05-29 45 views
5

这个问题是围绕着如何构建WCF服务,使其随着时间的推移而变得容易。 在不描述问题的情况下,很难获得对此的响应深度。WCF体系结构和Evolution,版本

背景

我开发的WCF服务和客户端的大系统。 服务器端很容易更新,因为只有10台服务器在运行该代码。

尽管自动化程度很高,客户仍然很难在300,000+ WCF客户端进行更新,但更新总是需要一些时间,并且只能在两到三周内获得较高的更新成功率。

数据契约

[DataContract] 
public class MyContract 
{ 
    [DataMember] 
    public int Identity {get; set;} 

    [DataMember] 
    public string Name {get; set;} 

    // More members 
} 

DataContract难以初始化并具有标准MyContractFactory类初始化获得相应的实例为您的机器。

public class static MyContractFactory 
{ 
    public static MyContract GetMyContract() 
    { 
     // Complex implementation 
    } 
} 

ServiceContracts

DataContract是通过一系列的网络服务非常普遍。

namespace MyPrefix.WebServicve1 
{ 
    [ServiceContract] 
    public class IMyInterface1 
    { 
     [OperationContract] 
     public void DoSomethingWithMyContract(MyContract data); 
    } 

    [ServiceContract] 
    public class IMyInterface2 
    { 
     [OperationContract] 
     public void DoSomethingDifferentWithMyContract(MyContract data); 
    } 
} 

客户

我的客户是基于在依赖于信任的水平,我们必须在插件使用单独的进程或应用程序域运行插件插件。

实现1

我的初步实施这个(默认WCF)的一个组件,ServiceContract,并实现在自己的装配结束了与DataContract

的客户几乎每个插件结束了一个非常难看,

MyWebService1.MyContract 
MyWebService2.MyContract 

随着MyContractFactory的复制和粘贴。虽然DataContract是相同的,但客户端不包含DataContract程序集这一事实意味着它出现在不同对象的不同名称空间下。

实现2个

的客户现在包括DataContract装配,ServiceContracts是在一个单独的装配服务实现,客户端可能包括一些ServiceContract组件是否会与代码重用(不再拷贝援助和粘贴)。

问题

随着第二执行我现在面临的困难,我该如何更新我的DataContractServiceContracts

  1. 我是否更新相同的程序集并增加版本号?在所有客户端升级时如何保持向后兼容性?打破客户,直到他们更新是不可接受的。

  2. 我是否创建了一个新类,该类扩展了MyDataContract,在新的ServiceContract下接受新类型的新方法?这是否意味着我的合同的每一个小改动都需要一个新的程序集?在几年的时间内,我会如何阻止它达到数百个?

  3. 其他一些解决方案?

无论我认为通过什么解决方案,他们都似乎有一个主要的缺点。

似乎没有要(至少我)的,

  • 保留向后兼容,直到客户更新
  • 保持客户没有膨胀修剪作为软件的发展随着时间的推移
  • 没有明显污染我的ServiceContractOperationContract的过载需要一个新的“名称”)。我已经有了像下面这样的东西,它让我觉得随着时间的推移而噩梦。

经营合同的复杂性

[OperationContract] 
public void DoSomethingWithMyContract(MyContract data); 

[OperationContract(Name = "DoSomethingWithMyDataByAdditionalData"] 
public void DoSomethingWithMyContract(MyContract data, MyContract2 additionalData); 

我寻找已超过在大型环境中一段时间​​工作的解决方案。博客条目等非常受欢迎。

更新1

翻翻使用“无模式”的变化的限制,不同的命名空间似乎是唯一可靠的方法。然而,它并不像预期的那样工作,例如,下面

[ServiceContract(
    Name = "IServiceContract", 
    Namespace = "http://myurl/2012/05")] 
public interface IServiceContract1 
{ 
    // Some operations 
} 

[ServiceContract(
    Name = "IServiceContract", 
    Namespace = "http://myurl/2012/06")] 
public interface IServiceContract2 
{ 
    // Some different operations using new DataContracts 
} 

有以下服务

public class MyService : IServiceContract1, IServiceContract2 
{ 
    // Implement both operations 
} 

及以下配置

<service behaviorConfiguration="WcfServiceTests.ServiceBehavior" 
    name="Test.MyService"> 
    <endpoint 
     address="2012/05" 
     binding="wsHttpBinding" 
     contract="Test.IServiceContract1"> 
     <identity> 
     <dns value="localhost" /> 
     </identity> 
    </endpoint> 
    <endpoint 
     address="2012/06" 
     binding="wsHttpBinding" 
     contract="Test.IServiceContract2"> 
     <identity> 
     <dns value="localhost" /> 
     </identity> 
    </endpoint> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
    </service> 

结果两个合同有两个不同的名字,我希望我能指出我的客户,

http://myurl.com/MyService.svc/2012/05旧版本和http://myurl.com/MyService.svc/2012/06

,但似乎如果我想保留ServiceContract名称,它们必须是两个单独的服务,而不是同一服务的单独端点地址?

更新2

我最终使用我已下更新1中描述的方法。虽然WSDL看起来不正确,但是当我测试过这个服务时,该服务确实向下兼容老客户端。

回答

5

微软和大多数受尊重的WCF专家都可能会说同样的事情:版本控制应该使用合同名称空间来处理。

我不要吝啬你的组件的.NET命名空间 - 我指的是实际的WCF服务(和数据合同)命名空间 - 所以你应该有:

[ServiceContract(Namespace="http://services.yourcompany.com/Service1/V01"] 

什么等等 - 有些人喜欢通过一年的版本/月:

[ServiceContract(Namespace="http://services.yourcompany.com/Service1/2012/05"] 

这可以让你有相同服务的多个版本,只要客户来使用旧版本(由服务命名空间表示)打电话,他们会得到旧版本(只要你仍然公开)。

请参见:

+0

@马克-S一些伟大的答案在这些链接,谢谢!仍然消化它们 –

+0

@ marc-s似乎你不能保留相同的合约名称? –

+1

@MAfifi:不 - 你也不应该!这是一个基本原则,像服务合同这样的界面是**不可变的** - 如果你需要添加一些东西给它,你需要给它一个新的名字。当然,你应该**永远不会**通过改变例如打破现有界面。参数的数量或数据类型... –