这个问题是围绕着如何构建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
组件是否会与代码重用(不再拷贝援助和粘贴)。
问题
随着第二执行我现在面临的困难,我该如何更新我的DataContract
和ServiceContracts
?
我是否更新相同的程序集并增加版本号?在所有客户端升级时如何保持向后兼容性?打破客户,直到他们更新是不可接受的。
我是否创建了一个新类,该类扩展了
MyDataContract
,在新的ServiceContract
下接受新类型的新方法?这是否意味着我的合同的每一个小改动都需要一个新的程序集?在几年的时间内,我会如何阻止它达到数百个?其他一些解决方案?
无论我认为通过什么解决方案,他们都似乎有一个主要的缺点。
似乎没有要(至少我)的,
- 保留向后兼容,直到客户更新
- 保持客户没有膨胀修剪作为软件的发展随着时间的推移
- 没有明显污染我的
ServiceContract
(OperationContract
的过载需要一个新的“名称”)。我已经有了像下面这样的东西,它让我觉得随着时间的推移而噩梦。
经营合同的复杂性
[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看起来不正确,但是当我测试过这个服务时,该服务确实向下兼容老客户端。
@马克-S一些伟大的答案在这些链接,谢谢!仍然消化它们 –
@ marc-s似乎你不能保留相同的合约名称? –
@MAfifi:不 - 你也不应该!这是一个基本原则,像服务合同这样的界面是**不可变的** - 如果你需要添加一些东西给它,你需要给它一个新的名字。当然,你应该**永远不会**通过改变例如打破现有界面。参数的数量或数据类型... –