2012-03-22 71 views
2

想象一下,這是我的情景:如何在Xml中序列化派生類?

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(); 
    } 
+0

什麼是例外?你有什麼嘗試? – Vache 2012-03-22 21:19:52

+0

什麼是例外文本?我敢打賭,它抱怨已知的類型,並告訴你該怎麼做。 – 2012-03-22 21:20:25

+0

@Vache這是我的錯誤:生成XML文檔時發生錯誤。 – 2012-03-22 21:24:07

回答

12

你必須告訴串行有關的派生類型

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

這是選擇.NET異常,是真正有用的一個。如果你看的InnerException,你會看到

The type FooA was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

UPDATE

基於您對不同模塊中的許多派生類型的註釋,你還可以指定派生類型在運行時創建序列化,而不是當在編譯時:

How to add XmlInclude attribute dynamically

0

這裏是一個很好的可重複使用的方法:

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; 

}