我的结构如下:
public interface A
{
public void method();
}
public class B : A
{
}
public class C : A
{
}
List<A> list;
List包含B和C类型的对象,它们还有一些我想保留的字段,我现在可以序列化它,反序列化并获取正确的对象实例吗? 最好是XML
编辑:
有没有简单的方法来序列化包含接口的列表,然后将其反序列化回B和C实例?
答案 0 :(得分:6)
假设您正在使用内置的.net XML序列化,您应该查看以下属性:
System.Xml.Serialization.XmlIncludeAttribute
它允许您在序列化/反序列化时指示序列化程序包含其他类型。
向列表添加新类型而不更新序列化元数据是常见的错误来源,请确保您有足够的测试覆盖率。
答案 1 :(得分:5)
我会使用抽象类而不是接口(因为无法序列化某种类型的接口),然后使用XmlInclude属性对类型进行硬编码,我会在串行和反序列化中将已知类型添加到XmlSerializer中像这样的方法:
string listXml = Serialize<List<A>>(ListA, new Type[] { typeof(B), typeof(C) });
List<IA> NewList = Deserialize<List<A>>(listXml, new Type[] { typeof(B), typeof(C) });
private static T Deserialize<T>(string Xml, Type[] KnownTypes)
{
XmlSerializer xs = new XmlSerializer(typeof(T),KnownTypes);
StringReader sr = new StringReader(Xml);
return (T)xs.Deserialize(sr);
}
private static string Serialize<T>(Object obj, Type[] KnownTypes)
{
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
XmlSerializer xs = new XmlSerializer(typeof(T), KnownTypes);
xs.Serialize(sw, obj);
}
return sb.ToString();
}
答案 2 :(得分:4)
是的,但您必须使用XmlElement,XmlRoot和XmlArray属性。 每个Type都需要它自己的元素名称。
编辑:一些示例代码。所有类都派生自一个公共基类。
以下是示例代码:
[XmlRoot(ElementName="Root")]
public sealed class SomeObject
{
private BaseObject _Object;
[XmlElement(Type=typeof(App.Projekte.Projekt), ElementName="Projekt")]
[XmlElement(Type=typeof(App.Projekte.Task), ElementName="Task")]
[XmlElement(Type=typeof(App.Projekte.Mitarbeiter), ElementName="Mitarbeiter")]
public BaseObject Object
{
get
{
return _Object;
}
set
{
_Object = value;
}
}
}
编辑:删除序列化属性,因为它不需要(但在代码来自我的项目中需要)
答案 3 :(得分:4)
您可以尝试使用DataContractSerializer:
public interface A
{
}
public class B : A
{
}
public class C : A
{
}
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>(new A[] { new B(), new C() });
var serializer = new DataContractSerializer(
list.GetType(), new[] { typeof(B), typeof(C) });
var sb = new StringBuilder();
using (var stringWriter = new StringWriter(sb))
using (var writer = XmlWriter.Create(stringWriter))
{
serializer.WriteObject(writer, list);
}
using (var stringReader = new StringReader(sb.ToString()))
using (var reader = XmlReader.Create(stringReader))
{
list = (List<A>)serializer.ReadObject(reader);
}
}
}
答案 4 :(得分:0)
对于你的情况,创建一个实现你的界面的抽象类,如:
abstract class Abs : A
然后从Abs
派生你的类public class B : Abs
public class C : Abs
和 清单清单;
现在使用XmlIncludeAttribute将您的类型添加到XmlSerializer的类型数组中。
答案 5 :(得分:0)
XmlSerializer
不适用于接口。所以你可以:
将接口转换为抽象类,然后使用XmlIncludeAttribute
或将{KnownTypes提供给XmlSerializer
或
为父类型
实施IXmlSerializable
或
考虑使用.NET 3.0中的DataContractSerializer