【问题标题】:How to support both DataContractSerializer and XMLSerializer for the same contract on the same host?如何为同一主机上的同一合约同时支持 DataContractSerializer 和 XMLSerializer?
【发布时间】:2011-03-02 19:56:34
【问题描述】:

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

我们有一个约束:我们不想重新定义每个合约接口两次,我们有 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)

【问题讨论】:

    标签: c# .net wcf xml-serialization datacontractserializer


    【解决方案1】:

    简短的回答是,您不能,因为您的错误消息所说的确切原因,您不能有太多具有相同名称的端点,而实际上您正在尝试这样做。我认为你必须完全按照你说你不想做的事情去做。

    This might be your only option

    问题是要指定一个 服务是使用 XmlSerializer 你需要声明 [XmlSerializerFormat] 属性 服务或合同。好吧,因为 我们想对两者都使用相同的 我们不能把它放在那里的端点,所以 我们只剩下把它放在 合同。然而,当它沸腾时 对它来说,两个端点都在使用 相同的服务和替代相同 合同对吗?

    嗯,不必如此。你 可以有一个合同 A 来自 合同B,然后有服务 执行合同 A 使得 两份合同中的所有内容都是一部分 的服务。对于这个例子 但是,合同 B 将是我们的 标准合同,合同 A 将 是一个只定义 [XmlSerializerFormat] 属性。

    但我不能向您保证,无需更改即可与您现有的客户代码一起使用。

    【讨论】:

      【解决方案2】:

      只需使用 [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>
      

      您显然可以强制命名空间,使它们都完全匹配。这仅用于示例目的。

      【讨论】:

        【解决方案3】:

        如果让两个服务实现同一个合同呢?

        喜欢:

        class DcsService : Service
        {}
        
        [XmlSerializerFormat] 
        class XmlService : Service
        {}
        
        class Service : IServiceContract
        {}
        

        从未使用过 XmlSerializer,但我们将此构造用于其他目的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-02
          • 2012-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多