代码之家  ›  专栏  ›  技术社区  ›  Sylvain

如何为同一主机上的同一契约同时支持DataContractSerializer和XmlSerializer?

  •  5
  • Sylvain  · 技术社区  · 14 年前

    在我们的生产环境中,我们的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)
    
    3 回复  |  直到 14 年前
        1
  •  1
  •   Serapth    14 年前

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

    This might be your only option

    问题是要指定 服务将使用XmlSerializer 你需要申报 上的[xmlserializerformat]属性 服务或合同。井自 我们两个都要用同样的 端点我们可以放在那里,所以 我们把它放在 合同。然而,当它结束的时候 对于它,两个端点都使用 相同的服务和替代相同 合同权利?

    好吧,不一定非得这样。你 可以有一个合同 合同B,然后开始服务 执行合同A,以便 两份合同中的一切都是部分的 服务。对于这个例子 但是,合同B将是我们的 标准合同和合同A遗嘱 只是定义 [xmlserializerformat]属性。

    但是我不能保证在不做更改的情况下使用现有的客户机代码。

        2
  •  1
  •   CkH    14 年前

    只需使用[datacontract]和[datamember]标记创建对象。XmlSerializer和DataContractSerializer都可以对对象进行序列化。他们更新了3.0框架中的XmlSerializer来处理DataContract序列化。DataContractSerializer可以处理[可序列化]对象,但行为不准确,需要进行一些调整。

    只需使用数据契约创建所有对象。这样你就不用担心打两个电话(一个接一个)。可以使用XmlSerializer或DataContractSerializer,但不能有任何问题。

    如果需要添加Behavior属性,您可以随时添加[可序列化]和[数据合同]。

    [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
  •  0
  •   Alex    14 年前

    让两个服务执行同一个合同怎么样?

    像:

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

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