简体   繁体   English

XML版本特定的反序列化

[英]XML version-specific deserialization

So, I have a base project and several modified version of it. 因此,我有一个基础项目及其几个修改版本。 BaseProject contains class BaseClass , BaseProject包含类BaseClass

namespace BaseProject.SomeClasses{
    public abstract class BaseClass{
    //...
    }
}

while each of the versions contain several inheritors of BaseClass - fe ProjectOne : 而每个版本都包含BaseClass的多个继承者-fe ProjectOne

namespace BaseProject.VersionOne.SomeClasses{
    public class InheritorClass : BaseClass{
    //Some logic here...
    }
}

and ProjectTwo : ProjectTwo

namespace BaseProject.VersionTwo.SomeClasses{
    public class InheritorClass : BaseClass{
    //Some different logic here...
    }
}

The only thing that differs is the name of the namespace. 唯一不同的是名称空间的名称。

Base project loads each of the assemblies during the runtime and gets all of the inherited types. 基础项目在运行时加载每个程序集,并获取所有继承的类型。 I need to create the xml file, which should contain both of the inheritors' instances and some pointers to the class which the instance should be deserialized into: 我需要创建xml文件,该文件应包含继承者的实例和指向该实例应反序列化为的类的一些指针:

...
<BaseClass xsi:type="InheritorClass"> <!-- From VersionOne -->
    <PropOne></PropOne>
    <PropTwo></PropTwo>
    <PropThree></PropThree>
    <!-- ... -->
</BaseClass>
<BaseClass xsi:type="InheritorClass"> <!-- From VersionTwo -->
    <PropFour></PropFour>
    <PropFive></PropFive>
    <PropSix></PropSix>
    <!-- ... -->
</BaseClass>
...

Is there any way to deserialize this xml (which contains the instances of inheritors from both of the versions) into IEnumerable<BaseClass> ? 有没有办法将此xml(包含两个版本的继承者的实例)反序列化为IEnumerable<BaseClass>

The namespace of the class shouldn't make a difference. 该类的名称空间不应有所作为。 See XML file generate by this code. 请参阅此代码生成的XML文件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            Root root = new Root()
            {
                baseClass = new List<BaseClass>(){
                    new InheritorClass1(){ name = "class1"},
                    new InheritorClass2(){ name = "class2"}
                }
            };
            XmlSerializer serializer = new XmlSerializer(typeof(Root));

            StreamWriter writer = new StreamWriter(FILENAME);
            serializer.Serialize(writer, root);
            writer.Flush();
            writer.Close();
            writer.Dispose();

            XmlSerializer xs = new XmlSerializer(typeof(Root));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            Root newRoot = (Root)xs.Deserialize(reader);
        }
    }
    [XmlRoot("Root")]
    public class Root
    {
        [XmlElement("BaseClass")]
        public List<BaseClass> baseClass { get; set; }
    }
    [XmlRoot("BaseClass")]
    [XmlInclude(typeof(InheritorClass1))]
    [XmlInclude(typeof(InheritorClass2))]
    public class BaseClass
    {
        [XmlElement("name")]
        public string name { get; set; }    

    }
    [XmlRoot("InheritorClass1")]
    public class InheritorClass1 : BaseClass
    {
    }

    [XmlRoot("InheritorClass2")]
    public class InheritorClass2 : BaseClass
    {
    }

}
​

You need to apply the [XmlTypeAttribute(name)] attribute to your derived classes to disambiguate the xst:type names: 您需要将[XmlTypeAttribute(name)]属性应用于派生类,以消除xst:type名称的歧义:

namespace BaseProject.VersionOne.SomeClasses
{
    [XmlType("VersionOneInheritorClass")]
    public class InheritorClass : BaseClass
    {
        public string VersionOneProperty { get; set; } // For instance
    }
}

and

namespace BaseProject.VersionTwo.SomeClasses
{
    [XmlType("VersionTwoInheritorClass")]
    public class InheritorClass : BaseClass
    {
        public string VersionTwoProperty { get; set; } // For instance
    }
}

Then your XML will appear as follows, and can be serialized and deserialized successfully without loss of information: 然后,您的XML将显示如下,并且可以成功进行序列化和反序列化而不会丢失信息:

 <BaseClass xsi:type="VersionOneInheritorClass"> <VersionOneProperty>one</VersionOneProperty> </BaseClass> <BaseClass xsi:type="VersionTwoInheritorClass"> <VersionTwoProperty>two</VersionTwoProperty> </BaseClass> 

By the way, if you are constructing an XmlSerializer using the XmlSerializer (Type, Type[]) constructor to add in your discovered derived types, you must cache the serializer in a static cache somewhere , or else you will have a horrible resource leak. 顺便说一句,如果你正在建设一个XmlSerializer使用XmlSerializer (Type, Type[])构造函数来在你发现派生类型添加,则必须某处缓存串行静态缓存 ,否则你将有一个可怕的资源泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM