.NET XML序列化和继承

mic*_*ael 11 c# inheritance serialization xml-serialization

我有这样的结构:

public interface A
{
    public void method();
}

public class B : A
{
}

public class C : A
{
}

List<A> list;
Run Code Online (Sandbox Code Playgroud)

List包含B和C类型的对象,它们还有一些我想保留的字段,我现在可以序列化它,反序列化并获取正确的对象实例吗?最好是XML

编辑:

是否有任何简单的方法来序列化包含接口的列表,然后将其反序列化回B和C实例?

jon*_*nii 6

假设您正在使用内置的.net XML序列化,您应该看看以下属性:

System.Xml.Serialization.XmlIncludeAttribute
Run Code Online (Sandbox Code Playgroud)

它允许您在序列化/反序列化时指示序列化程序包含其他类型.

向列表中添加新类型而不更新序列化元数据是错误的常见原因,请确保您有足够的测试覆盖率.


CkH*_*CkH 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();
    }
Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 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);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)