2010-06-11 25 views
5

在我们的生产环境中,我们的WCF服务使用XMLSerializer进行序列化。为此,我们的服务接口具有[XMLSerializerFormat]属性。现在,我们需要更改为DataContractSerializer,但我们必须保持与现有客户端的兼容性。因此,我们必须使用两个序列化器来公开每个服务。如何在同一主机上同时支持DataContractSerializer和XMLSerializer?

我们有一个约束:我们不想重新定义每个合同接口的两倍,我们有50个服务合同接口,我们不希望有

IIncidentServiceXml 
IIncidentServiceDCS 
IEmployeeServiceXml 
IEmployeeServiceDCS 
IContractServiceXml 
IContractServiceDCS 

我们怎样才能做到这一点?


更多信息

这是一个什么样我们迄今尝试了说明,但我愿意尝试完全不同的方法:

我们试图通过创建代码的所有端点在我们自己的ServiceHostFactory类中。基本上我们创建两个端点。问题是,在运行时,WCF抱怨服务有两个端点具有相同的联系人名称,但具有不同的ContractDescription实例。该消息表示我们应该使用不同的合约名称或重复使用相同的ContractDescription实例。

其他尝试:

我们也尝试通过使用不同的命名空间为每个ContractDescription实例来做到这一点。这样,我们将保持相同的合同接口(IIncidentService),但有两个不同的命名空间:

http://ourcompany/XML/IIncidentService 
http://ourcompany/DCS/IIncidentService 

有了,我们能够获得远,但服务有一个奇怪的异常崩溃:

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: 
System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.XmlSerializerOperationBehavior 
contract: http://ourcompany.cs/XML:IUserServiceWCF ----> System.NullReferenceException: Object reference not set to an instance of an object. 
    at System.ServiceModel.Description.XmlSerializerMessageContractExporter.ExportFaults(Object state) 
    at System.ServiceModel.Description.MessageContractExporter.ExportMessageContract() 
    at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext contractContext) 
    at System.ServiceModel.Description.WsdlExporter.CallExtension(WsdlContractConversionContext contractContext, IWsdlExportExtension extension) 

回答

1

短答案是,你不能,正是你的错误信息所说的原因,你不能有太多有效的终结点,你试图做的。我认为你将不得不做你说你不想要的。

This might be your only option

的问题是,指定 服务是使用XmlSerializer 需要声明的 服务或合同 [XmlSerializerFormat]属性。自从 我们想要使用相同的两个 端点我们不能将它放在那里,所以 我们将它放在 合同上。但是,当它归结为 时,两个终端都使用 相同的服务和代理合同 合同吗?

那么,它并不一定如此。你 可以有一个合同A衍生自 合同B,然后有服务 执行合同A,使得 两个合同中的一切都是 的服务。对于这个例子 虽然,合同B将是我们的 标准合同,合同A将 是一个界面,只是定义了 [XmlSerializerFormat]属性。

但我不能向您保证,这将与您现有的客户端代码一起工作,无需更改。

+0

我已经用另一次尝试更新了我的问题 – Sylvain 2010-06-11 20:22:16

0

如何让两个服务实现相同的合同?

像:

class DcsService : Service 
{} 

[XmlSerializerFormat] 
class XmlService : Service 
{} 

class Service : IServiceContract 
{} 

决不XmlSerializer的工作,但我们使用这种结构用于其它目的。

1

只需使用[DataContract]和[DataMember]标签创建您的对象。 XmlSerializer和DataContractSerializer都会对对象进行序列化。他们更新了3.0框架中的XmlSerializer以处理数据合同序列化。 DataContractSerializer可以处理[Serializable]对象,但行为并不准确,需要进行一些调整。

只需使用数据合约制作所有对象。这样你就不必担心打两个电话(每个电话一个)。您可以毫无问题地使用XmlSerializer或DataContractSerializer。

如果你需要添加行为属性,你可以随时添加[Serializable]和[DataContract],如果你喜欢。

[Serializable] 
[DataContract] 
public class Customer 

{ 
    [DataMember] 
    public int Age { get; set; } 

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

    [DataMember] 
    public int Number { get; set; } 

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

    [XmlIgnore] 
    public int IgnoredNumber { get; set; } 
} 

的XmlSerializer序列化为:

<?xml version="1.0" encoding="utf-16" ?> 
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Age>88</Age> 
    <Name>Bob</Name> 
    <Number>808</Number> 
    <FullName>Bob Jones</FullName> 
    </Customer> 

的DataContractSerializer序列化为:

<?xml version="1.0" encoding="utf-8" ?> 
<Customer xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1"> 
    <Age>88</Age> 
    <FullName>Bob Jones</FullName> 
    <Name>Bob</Name> 
    <Number>808</Number> 
    </Customer> 

可以很明显的强制命名空间,因此它们都完全匹配。这仅仅是为了举例。

相关问题