XML 特定于版本的反序列化
XML version-specific deserialization
所以,我有一个基础项目和它的几个修改版本。 BaseProject 包含 class BaseClass,
namespace BaseProject.SomeClasses{
public abstract class BaseClass{
//...
}
}
而每个版本都包含 BaseClass - f.e 的几个继承者。 ProjectOne:
namespace BaseProject.VersionOne.SomeClasses{
public class InheritorClass : BaseClass{
//Some logic here...
}
}
和ProjectTwo:
namespace BaseProject.VersionTwo.SomeClasses{
public class InheritorClass : BaseClass{
//Some different logic here...
}
}
唯一不同的是命名空间的名称。
基础项目在运行时加载每个程序集并获取所有继承类型。我需要创建 xml 文件,该文件应包含继承者的实例和一些指向 class 的指针,实例应反序列化为:
...
<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>
...
有什么方法可以将这个 xml(包含两个版本的继承者的实例)反序列化为 IEnumerable<BaseClass>
?
class 的命名空间应该没有什么区别。请参阅此代码生成的 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
{
}
}
您需要将 [XmlTypeAttribute(name)]
属性应用于派生的 类 以消除 xst:type
名称的歧义:
namespace BaseProject.VersionOne.SomeClasses
{
[XmlType("VersionOneInheritorClass")]
public class InheritorClass : BaseClass
{
public string VersionOneProperty { get; set; } // For instance
}
}
和
namespace BaseProject.VersionTwo.SomeClasses
{
[XmlType("VersionTwoInheritorClass")]
public class InheritorClass : BaseClass
{
public string VersionTwoProperty { get; set; } // For instance
}
}
那么你的XML会出现如下,可以序列化反序列化成功,不丢失信息:
<BaseClass xsi:type="VersionOneInheritorClass">
<VersionOneProperty>one</VersionOneProperty>
</BaseClass>
<BaseClass xsi:type="VersionTwoInheritorClass">
<VersionTwoProperty>two</VersionTwoProperty>
</BaseClass>
顺便说一下,如果您使用 XmlSerializer (Type, Type[])
constructor to add in your discovered derived types, you must cache the serializer in a static cache somewhere 构建 XmlSerializer
,否则您将遇到可怕的资源泄漏。
所以,我有一个基础项目和它的几个修改版本。 BaseProject 包含 class BaseClass,
namespace BaseProject.SomeClasses{
public abstract class BaseClass{
//...
}
}
而每个版本都包含 BaseClass - f.e 的几个继承者。 ProjectOne:
namespace BaseProject.VersionOne.SomeClasses{
public class InheritorClass : BaseClass{
//Some logic here...
}
}
和ProjectTwo:
namespace BaseProject.VersionTwo.SomeClasses{
public class InheritorClass : BaseClass{
//Some different logic here...
}
}
唯一不同的是命名空间的名称。
基础项目在运行时加载每个程序集并获取所有继承类型。我需要创建 xml 文件,该文件应包含继承者的实例和一些指向 class 的指针,实例应反序列化为:
...
<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>
...
有什么方法可以将这个 xml(包含两个版本的继承者的实例)反序列化为 IEnumerable<BaseClass>
?
class 的命名空间应该没有什么区别。请参阅此代码生成的 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
{
}
}
您需要将 [XmlTypeAttribute(name)]
属性应用于派生的 类 以消除 xst:type
名称的歧义:
namespace BaseProject.VersionOne.SomeClasses
{
[XmlType("VersionOneInheritorClass")]
public class InheritorClass : BaseClass
{
public string VersionOneProperty { get; set; } // For instance
}
}
和
namespace BaseProject.VersionTwo.SomeClasses
{
[XmlType("VersionTwoInheritorClass")]
public class InheritorClass : BaseClass
{
public string VersionTwoProperty { get; set; } // For instance
}
}
那么你的XML会出现如下,可以序列化反序列化成功,不丢失信息:
<BaseClass xsi:type="VersionOneInheritorClass"> <VersionOneProperty>one</VersionOneProperty> </BaseClass> <BaseClass xsi:type="VersionTwoInheritorClass"> <VersionTwoProperty>two</VersionTwoProperty> </BaseClass>
顺便说一下,如果您使用 XmlSerializer (Type, Type[])
constructor to add in your discovered derived types, you must cache the serializer in a static cache somewhere 构建 XmlSerializer
,否则您将遇到可怕的资源泄漏。