【问题标题】:How to serialize derived classes in a Xml?如何序列化 Xml 中的派生类?
【发布时间】:2012-03-22 21:18:14
【问题描述】:

想象一下这是我的场景:

public abstract class Foo
{
    public abstract int X { get; set; }
}

public class FooA : Foo
{
    public override int X { get; set; }
    public int Y { get; set; }
}

public class FooB : Foo
{
    public override int X { get; set; }
    public int Z { get; set; }
}

这是一项服务,我有一些对象要序列化。

public class FooService
{
    public List<Foo> GetModels()
    {
        return new List<Foo>()
        {
            new FooA() { X = 3, Y = 6 },
            new FooB() { X = 5, Z = 10 }
        };
    }
}

这是我无法序列化对象的方法,它会引发异常。我想序列化派生类。

    private void SerializeObjects()
    {
        FooService service = new FooService();
        var a = service.GetModels();

        XmlSerializer x = new XmlSerializer(a.GetType());
        TextWriter writer = new StreamWriter("A.xml");

        x.Serialize(writer, a);
        writer.Close();
    }

【问题讨论】:

  • 有什么异常?你试过什么?
  • 异常文本是什么?我敢打赌,它是在抱怨已知类型并告诉你如何处理它。
  • @Vache 这是我的错误:生成 XML 文档时出错。
  • 这些类都没有 XML 属性声明。您必须通过装饰 Foo、FooA、FooB 等的属性和属性来告诉序列化程序要序列化什么
  • 内部异常告诉你"The type FooA was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically." :-)

标签: c# xml serialization xml-serialization


【解决方案1】:

你必须告诉序列化器派生类型

[XmlInclude(typeof(FooA))]
[XmlInclude(typeof(FooB))]
public abstract class Foo
{
    public abstract int X { get; set; }
}

这是真正有用的选择 .Net 异常之一。如果您查看 InnerException,您会看到

类型 FooA 不是预期的。使用 XmlInclude 或 SoapInclude 属性来指定静态未知的类型。

更新

根据您对不同模块中许多派生类型的评论,您还可以在创建序列化程序时而不是在编译时在运行时指定派生类型:

How to add XmlInclude attribute dynamically

【讨论】:

    【解决方案2】:

    这是一个很好的可重用方法:

    string sSerialData = "";
    
    SerializeQueueType<BaseClassType>(oDerivedObject, out sSerialData)
    
    
    private bool SerializeDerivedObject<T>(T oDerivedObject, out string sOutput)
    {
        bool bReturn = false;
    
        sOutput = "";
    
        try
        {
    
            Type[] arrTypes = new Type[1];
            arrTypes[0] = oDerivedObject.GetType();
    
            XmlSerializer xmlSerl = new XmlSerializer(typeof(T), arrTypes); 
            System.IO.MemoryStream memStream = new System.IO.MemoryStream();
            xmlSerl.Serialize(memStream, oDerivedObject); 
    
            memStream.Position = 0;
    
            using (var reader = new System.IO.StreamReader(memStream, Encoding.UTF8))
            {
                sOutput = reader.ReadToEnd();
            }
    
            bReturn = true;
    
        }
        catch (Exception ex)
        {
            //_log.Error(ex);
        }
    
    
        return bReturn;
    
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-03
      • 1970-01-01
      相关资源
      最近更新 更多