使用的DataContractSerializer和XmlSerializer的XML序列化 [英] XML Serialization using DataContractSerializer and XmlSerializer

查看:358
本文介绍了使用的DataContractSerializer和XmlSerializer的XML序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个服务引用(WCF)。

  • 第一视觉工作室使用的DataContractSerializer产生code
  • 第二个时,Visual Studio生成使用XmlSerializer的code

我不能更改Web服务器端任何东西。

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

我如何可以序列化此对象,它尊重了序列化规范的DataContractSerializer的和一个XmlSerializer的。  如果我使用的DataContractSerializer我会每场从我参考2序列一样,

 <的dataField>
 

而不是

 <数据>
 

由于它系列化只有默认的私有字段(??)

如果我在我的参考用XmlSerializer的每一个字符串数组2将被序列化一样,

 < myArray的>
<字符串>测试< /串>
<字符串>测试< /串>
< / myArray的>
 

而不是

 < myArray的>
<网址>测试< / URL>
<网址>测试< / URL>
< / myArray的>
 

因为它忽略了属性CollectionDataContractAttribute以指明如何每个项目阵列中的序列化。

那么,这将是您的解决方案?

我的第一个解决方案是将全部添加好醇'Web引用,但也许有一些很好的解决方案。

编辑:

下面是从1 / web服务类型(datcontract,WCF风格)

的声明

  [System.Diagnostics.DebuggerStepThroughAttribute()]
[系统。codeDom.Compiler.Generated codeAttribute(System.Runtime.Serialization,4.0.0.0)]
[System.Runtime.Serialization.DataContractAttribute(NAME =productInformations,命名空间=htt​​p://abcedf.net/)
[System.SerializableAttribute()]
公共部分类productInformations:对象,System.Runtime.Serialization.IExtensibleDataObject,System.ComponentModel.INotifyPropertyChanged {
 

解决方案

第一个问题:既然通过添加Web引用生成的类型都装饰有 [Serializable接口] 默认情况下,所使用的的DataContractSerializer 的序列化模式是所有的字段的(公共或)被序列化。如果你装饰与 [DataContract] 和成员的类型你想序列化(属性)与 [数据成员] 。 A型可以有两个串行器没有问题的属性,如下所示。

 公共类StackOverflow_7348240
{
    [可序列化]
    [DataContract(NAME =myRoot,命名空间=)]
    [XmlRoot(的ElementName =myRoot,命名空间=)]
    公共类的MyType
    {
        私人字符串的dataField;

        [的XmlElement(的ElementName =数据)
        [数据成员(NAME =数据)
        公共字符串数据
        {
            {返回this.dataField; }
            集合{this.dataField =价值; }
        }
    }

    公共静态无效测试()
    {
        MyType的OBJ =新的MyType {数据=世界你好};

        MemoryStream的毫秒=新的MemoryStream();
        新的DataContractSerializer(obj.GetType())的writeObject(MS,OBJ)。
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        ms.SetLength(0);
        新的XmlSerializer(obj.GetType())序列化(MS,OBJ);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}
 

对于第二个问题,如果集合类是另一个对象的成员,也可以添加相应的属性(这个时候那些对XML序列化),即 [XmlArray] (指定集合名称)和 [XmlArrayItem] (指定项目名称),你可以有相同类型的序列化以同样的方式,就像在下面的例子。

 公共类StackOverflow_7348240_b
{
    [DataContract(NAME =myRoot,命名空间=)]
    [XmlRoot(的ElementName =myRoot,命名空间=)]
    公共类的MyType
    {
        [数据成员(NAME =myArray的)
        [XmlArray(的ElementName =myArray的)]
        [XmlArrayItem(的ElementName =URL)
        公共MYARRAY myArray的;
    }

    [CollectionDataContract(NAME =myArray的,命名空间=,=了itemnameURL)
    [XmlType将(命名空间=)]
    [XmlRoot(的ElementName =myArray的,命名空间=)]
    公共类MYARRAY:列表<字符串>
    {
    }

    公共静态无效测试()
    {
        MyType的OBJ =新的MyType {myArray的=新MYARRAY {一,二}};

        MemoryStream的毫秒=新的MemoryStream();
        新的DataContractSerializer(obj.GetType())的writeObject(MS,OBJ)。
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));

        ms.SetLength(0);
        新的XmlSerializer(obj.GetType())序列化(MS,OBJ);
        Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
    }
}
 

更新

予理解的是,你想合并类型手动,但基于注释不是这种情况。在这种情况下,如果你想同时使用添加Web引用(AWR),并添加服务引用(ASR),那么你就需要退回到普通串行,这是的XmlSerializer 。 AWR的总是的使用的XmlSerializer (XS),而ASR可以同时使用一个和的DataContractSerializer (DCS)。 DCS的是默认的一个用于ASR,但你可以改变它使用另一种。你有两个选择:

  • 使用svcutil.exe的(而不是ASR),并通过/串行:XmlSerializer的命令行
  • 添加服务引用后,打开Reference.svcmap文件(您可能需要选中显示所有文件选项的项目),然后更改选项<串行> 自动的XmlSerializer ,然后选择更新服务引用。

I have 2 service reference (WCF).

  • the first visual studio generate code using DataContractSerializer
  • the second one, visual studio generates code using XmlSerializer

I can't change anything on the web server side.

So I'm creating an object aggregating objects from both references.

How can I serialize this object so it respect the serialization specification for a DataContractSerializer and for a XmlSerializer. If I use a DataContractSerializer I'll have every field from my reference 2 serialized like that

<dataField>

instead of

<data>

because it serializes only the private fields by default (??)

and if I use a XmlSerializer every string array in my reference 2 will be serialized like that

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

instead of

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

because it ignores the attribute CollectionDataContractAttribute which specified how to serialize every item in the array.

So what would be your solution ?

My first solution would be to add all of them as good ol' web reference but maybe there is some nice solution.

EDIT :

here is the declaration of the type from the 1/ web service (datcontract,wcf style)

    [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 {

解决方案

The first problem: since the types generated by "Add Web Reference" are decorated with [Serializable] by default, the serializable model used by the DataContractSerializer is that all fields (public or not) are serialized. If you decorate the type with [DataContract] and the members you want serialized (the properties) with [DataMember]. A type can have the attributes for both serializers without problems, as shown below.

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()));
    }
}

For the second issue, if the collection type is a member of another object, you can also add the appropriate attributes (this time the ones for XML serialization), namely [XmlArray] (to specify the collection name) and [XmlArrayItem] (to specify the item name), and you can have the same type serialized the same way, like in the example below.

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()));
    }
}

Update

I understood that you wanted to merge the types "by hand", but based on the comment this is not the case. In this case, if you want to use both Add Web Reference (AWR) and Add Service Reference (ASR), then you'll need to fall back to the common serializer, which is the XmlSerializer. AWR always uses the XmlSerializer (XS), while ASR can use both that one and the DataContractSerializer (DCS). The DCS is the default one for ASR, but you can change it to use the other one. You have two options:

  • Use svcutil.exe (instead of ASR), and pass the /serializer:XmlSerializer command line
  • After adding the service reference, open the Reference.svcmap file (you may need to check the "Show All Files" option for the project), then change the option <Serializer> from Auto to XmlSerializer, then select "Update Service Reference".

这篇关于使用的DataContractSerializer和XmlSerializer的XML序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆