.NET(C#):XML序列化时派生类的处理

原文 www.cnblogs.com/mgen/archive/2011/12/03/2275014.html

 

注意:

运行代码请注意添加如下命名空间:

using System.Xml;

using System.Xml.Serialization;

using System.IO;

 

 

返回目录

1. 针对基类的XmlSerializer序列化派生类

派生类将会序列化成这样的XML:

<基类名称xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xmlns:xsd="http://www.w3.org/2001/XMLSchema"

         xsi:type="派生类名称">

    <!-- 基类和派生类的内容 -->

</基类名称>

 

第一种方法是在基类添加XmlInclude特性,这样的话基类的XmlSerializer可以序列化派生类了。

代码:

//基类加入XmlInclude

[XmlInclude(typeof(b))]

publicclassa

{

    publicint aaa;

}

publicclassb : a

{

    publicint bbb;

}

 

classProgram

{

    staticvoid Main()

    {

        var xs =newXmlSerializer(typeof(a));

        using (var textWriter =newStringWriter())

        {

            xs.Serialize(textWriter, newb());

            Console.WriteLine(textWriter);

        }

    }

}

 

输出XML:

<axmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema"

   xsi:type="b">

    <aaa>0</aaa>

    <bbb>0</bbb>

</a>

 

第二种方法就是在XmlSerializer的构造函数内指定派生类型,然后序列化,这样就不用在基类上加入XmlInclude特性了。

代码:

//无需加入XmlInclude

publicclassa

{

    publicint aaa;

}

publicclassb : a

{

    publicint bbb;

}

 

classProgram

{

    staticvoid Main()

    {

        var xs =newXmlSerializer(typeof(a), newType[] { typeof(b) });

        using (var textWriter =newStringWriter())

        {

            xs.Serialize(textWriter, newb());

            Console.WriteLine(textWriter);

        }

    }

}

输出和上面一样!

 

 

返回目录

2. 类内成员是派生类的序列化

还是上面的类a和b,现在再加入一个c类,这个c类中有一个a的对象:

publicclassa

{

    publicint aaa;

}

publicclassb : a

{

    publicint bbb;

}

 

publicclassc

{

    publica objA =newa();

}

 

此时直接XML序列化一个c对象,结果是这样的XML:

<cxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <objA>

        <aaa>0</aaa>

    </objA>

</c>

 

下面搞得复杂些,把c中的a对象改成这样:

publicclassc

{

    publica objA =newb();

}

此时仿佛又回到了文章第一个标题,如果直接序列化c的话,会抛出异常。那么按照上面第一个方法,先在a上加入XmlInclude特性,然后再序列化c对象。

全部代码:

[XmlInclude(typeof(b))]

publicclassa

{

    publicint aaa;

}

publicclassb : a

{

    publicint bbb;

}

 

publicclassc

{

    publica objA =newb();

}

 

classProgram

{

    staticvoid Main()

    {

        var xs =newXmlSerializer(typeof(c));

        using (var textWriter =newStringWriter())

        {

            xs.Serialize(textWriter, newc());

            Console.WriteLine(textWriter);

        }

    }

}

 

输出XML(根节点c省略):

<objAxsi:type="b">

    <aaa>0</aaa>

    <bbb>0</bbb>

</objA>

和标题1的第一个方法类似!

 

但是标题1的第二个方法在这里没法使用的,因为c类和b类没有任何继承关系,在针对c的XmlSerializer不可能加入b的类型。这里其实还 有一种方法,加入XmlElement特性,其中ElementName属性是最终的Xml元素名称,而Type属性是针对的类型,这里加入b类型,不过 最好把a类型也加入(因为字段类型是a,有可能被赋值为a的对象)。

全部代码:

//不需要加XmlInclude

publicclassa

{

    publicint aaa;

}

publicclassb : a

{

    publicint bbb;

}

 

publicclassc

{

    [XmlElement(ElementName ="b", Type =typeof(b))]

    [XmlElement(ElementName ="a", Type =typeof(a))]

    publica objA =newb();

}

 

classProgram

{

    staticvoid Main()

    {

        var xs =newXmlSerializer(typeof(c));

        using (var textWriter =newStringWriter())

        {

            xs.Serialize(textWriter, newc());

            Console.WriteLine(textWriter);

        }

    }

}

 

生成XML:

<cxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <b>

        <aaa>0</aaa>

        <bbb>0</bbb>

    </b>

</c>

 

作者:Mgen
出处:www.cnblogs.com/mgen
其他参考页面:我的软件和工程博客导读

你可能感兴趣的:(.net)