【问题标题】:XML Serialization using DataContractSerializer and XmlSerializer使用 DataContractSerializer 和 XmlSerializer 进行 XML 序列化
【发布时间】:2011-09-08 12:46:02
【问题描述】:

我有 2 个服务参考 (WCF)。

  • 第一个 Visual Studio 使用 DataContractSerializer 生成代码
  • 第二个,Visual Studio 使用 XmlSerializer 生成代码

我无法更改网络服务器端的任何内容。

所以我正在创建一个从两个引用聚合对象的对象。

如何序列化此对象,使其遵守 DataContractSerializer 和 XmlSerializer 的序列化规范。 如果我使用 DataContractSerializer,我会将参考 2 中的每个字段都像这样序列化

<dataField>

而不是

<data>

因为它默认只序列化私有字段 (??)

如果我使用 XmlSerializer,我的参考文献 2 中的每个字符串数组都会像这样被序列化

<myArray>
<string>test</string>
<string>test</string>
</myArray>

而不是

<myArray>
<url>test</url>
<url>test</url>
</myArray>

因为它忽略了 CollectionDataContractAttribute 属性,该属性指定如何序列化数组中的每个项目。

那么你的解决方案是什么?

我的第一个解决方案是将所有这些都添加为良好的网络参考,但也许有一些不错的解决方案。

编辑:

这是来自 1/ web 服务的类型声明(datcontract,wcf 样式)

    [System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="productInformations", Namespace="http://abcedf.net/")]
[System.SerializableAttribute()]
public partial class productInformations : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

【问题讨论】:

  • 所以我决定删除我的 wcf 参考并添加一些 Web 服务参考,但我仍在寻找答案。

标签: .net wcf web-services xml-serialization


【解决方案1】:

第一个问题:由于“添加Web引用”生成的类型默认用[Serializable]修饰,所以DataContractSerializer使用的可序列化模型是所有字段(无论是否公开) 被序列化。如果你用[DataContract] 装饰类型,用[DataMember] 来序列化你想要的成员(属性)。一个类型可以毫无问题地拥有两个序列化器的属性,如下所示。

public class StackOverflow_7348240
{
    [Serializable]
    [DataContract(Name = "myRoot", Namespace = "")]
    [XmlRoot(ElementName = "myRoot", Namespace = "")]
    public class MyType
    {
        private string dataField;

        [XmlElement(ElementName = "data")]
        [DataMember(Name = "data")]
        public string Data
        {
            get { return this.dataField; }
            set { this.dataField = value; }
        }
    }

    public static void Test()
    {
        MyType obj = new MyType { Data = "hello world" };

        MemoryStream ms = new MemoryStream();
        new DataContractSerializer(obj.GetType()).WriteObject(ms, obj);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        ms.SetLength(0);
        new XmlSerializer(obj.GetType()).Serialize(ms, obj);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}

对于第二个问题,如果集合类型是另一个对象的成员,也可以添加适当的属性(这次是用于XML序列化的),即[XmlArray](指定集合名称)和@987654327 @(指定项目名称),并且您可以将相同的类型以相同的方式序列化,如下例所示。

public class StackOverflow_7348240_b
{
    [DataContract(Name = "myRoot", Namespace = "")]
    [XmlRoot(ElementName = "myRoot", Namespace = "")]
    public class MyType
    {
        [DataMember(Name = "myArray")]
        [XmlArray(ElementName = "myArray")]
        [XmlArrayItem(ElementName = "url")]
        public MyArray myArray;
    }

    [CollectionDataContract(Name = "myArray", Namespace = "", ItemName = "url")]
    [XmlType(Namespace = "")]
    [XmlRoot(ElementName = "myArray", Namespace = "")]
    public class MyArray : List<string>
    {
    }

    public static void Test()
    {
        MyType obj = new MyType { myArray = new MyArray { "one", "two" } };

        MemoryStream ms = new MemoryStream();
        new DataContractSerializer(obj.GetType()).WriteObject(ms, obj);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        ms.SetLength(0);
        new XmlSerializer(obj.GetType()).Serialize(ms, obj);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}

更新

我知道您想“手动”合并类型,但根据评论,情况并非如此。在这种情况下,如果您想同时使用 Add Web Reference (AWR) 和 Add Service Reference (ASR),那么您需要回退到通用序列化程序,即XmlSerializer。 AWR 总是使用XmlSerializer (XS),而ASR 可以同时使用那个和DataContractSerializer (DCS)。 DCS 是 ASR 的默认设置,但您可以将其更改为使用另一个。你有两个选择:

  • 使用 svcutil.exe(而不是 ASR),并传递 /serializer:XmlSerializer 命令行
  • 添加服务引用后,打开Reference.svcmap文件(项目可能需要勾选“显示所有文件”选项),然后将选项&lt;Serializer&gt;Auto更改为XmlSerializer,然后选择“更新服务参考”。

【讨论】:

  • 这里的问题是,这些类是生成的(它是网络参考),所以使用你的解决方案,我必须重新声明它们(因为它们是部分的)并添加这个属性,然后是要重新声明的 440 个类。
  • 这就是我理解你正在做的事情:“所以我正在创建一个从两个引用聚合对象的对象。”。在这种情况下,由于 Web 引用始终使用 XmlSerializer,您可以强制“服务引用”也使用该序列化程序 - 这样您将获得兼容的对象。您可以使用svcutil 命令行(/serializer:XmlSerializer 选项)或在添加服务引用后打开 Reference.svcmap 文件并将&lt;Serializer&gt; 元素从Auto 更改为XmlSerializer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
相关资源
最近更新 更多