序列化包含多种不明类型的集合
序列化包含多種不明類型的集合
?代碼:/Files/zhuqil/Kirin.rar
導言:
?? 你是否曾經想過序列化構造對象,它里面有一個集合,這個集合包含接口或者抽象類?你是否不知道所有的你要序列化的類型?好吧,如果這樣,那么我可以幫助你。
使用代碼:
?? 讓我們開始.首先,你將要將采用下面的幫助類,將它粘貼到你的項目之中。它將幫助你只用一行代碼就能序列化一個對象為XML。
?
代碼 ///?<summary>///?一個用來序列化的通用類
///?</summary>
public?class?GenericSerializer
{
????///?<summary>
????///?Serializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?serialized.</typeparam>
????///?<param?name="obj">The?object?to?be?serialized.</param>
????///?<returns>String?representation?of?the?serialized?object.</returns>
????public?static?string?Serialize<T>(T?obj)
????{
????????XmlSerializer?xs?=?null;
????????StringWriter?sw?=?null;
????????try
????????{
????????????xs?=?new?XmlSerializer(typeof(T));
????????????sw?=?new?StringWriter();
????????????xs.Serialize(sw,?obj);
????????????sw.Flush();
????????????return?sw.ToString();
????????}
????????catch?(Exception?ex)
????????{
????????????throw?ex;
????????}
????????finally
????????{
????????????if?(sw?!=?null)
????????????{
????????????????sw.Close();
????????????????sw.Dispose();
????????????}
????????}
????}
????public?static?string?Serialize<T>(T?obj,?Type[]?extraTypes)
????{
????????XmlSerializer?xs?=?null;
????????StringWriter?sw?=?null;
????????try
????????{
????????????xs?=?new?XmlSerializer(typeof(T),?extraTypes);
????????????sw?=?new?StringWriter();
????????????xs.Serialize(sw,?obj);
????????????sw.Flush();
????????????return?sw.ToString();
????????}
????????catch?(Exception?ex)
????????{
????????????throw?ex;
????????}
????????finally
????????{
????????????if?(sw?!=?null)
????????????{
????????????????sw.Close();
????????????????sw.Dispose();
????????????}
????????}
????}
????///?<summary>
????///?Serializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?serialized.</typeparam>
????///?<param?name="obj">The?object?to?be?serialized.</param>
????///?<param?name="writer">The?writer?to?be?used?for?output?in?the?serialization.</param>
????public?static?void?Serialize<T>(T?obj,?XmlWriter?writer)
????{
????????XmlSerializer?xs?=?new?XmlSerializer(typeof(T));
????????xs.Serialize(writer,?obj);
????}
????///?<summary>
????///?Serializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?serialized.</typeparam>
????///?<param?name="obj">The?object?to?be?serialized.</param>
????///?<param?name="writer">The?writer?to?be?used?for?output?in?the?serialization.</param>
????///?<param?name="extraTypes"><c>Type</c>?array
????///???????of?additional?object?types?to?serialize.</param>
????public?static?void?Serialize<T>(T?obj,?XmlWriter?writer,?Type[]?extraTypes)
????{
????????XmlSerializer?xs?=?new?XmlSerializer(typeof(T),?extraTypes);
????????xs.Serialize(writer,?obj);
????}
????///?<summary>
????///?Deserializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?deserialized.</typeparam>
????///?<param?name="reader">The?reader?used?to?retrieve?the?serialized?object.</param>
????///?<returns>The?deserialized?object?of?type?T.</returns>
????public?static?T?Deserialize<T>(XmlReader?reader)
????{
????????XmlSerializer?xs?=?new?XmlSerializer(typeof(T));
????????return?(T)xs.Deserialize(reader);
????}
????///?<summary>
????///?Deserializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?deserialized.</typeparam>
????///?<param?name="reader">The?reader?used?to?retrieve?the?serialized?object.</param>
????///?<param?name="extraTypes"><c>Type</c>?array
????///???????????of?additional?object?types?to?deserialize.</param>
????///?<returns>The?deserialized?object?of?type?T.</returns>
????public?static?T?Deserialize<T>(XmlReader?reader,?Type[]?extraTypes)
???????
????{
????????XmlSerializer?xs?=?new?XmlSerializer(typeof(T),?extraTypes);
????????return?(T)xs.Deserialize(reader);
????}
????///?<summary>
????///?Deserializes?the?given?object.
????///?</summary>
????///?<typeparam?name="T">The?type?of?the?object?to?be?deserialized.</typeparam>
????///?<param?name="XML">The?XML?file?containing?the?serialized?object.</param>
????///?<returns>The?deserialized?object?of?type?T.</returns>
????public?static?T?Deserialize<T>(string?XML)
????{
????????if?(XML?==?null?||?XML?==?string.Empty)
????????????return?default(T);
????????XmlSerializer?xs?=?null;
????????StringReader?sr?=?null;
????????try
????????{
????????????xs?=?new?XmlSerializer(typeof(T));
????????????sr?=?new?StringReader(XML);
????????????return?(T)xs.Deserialize(sr);
????????}
????????catch?(Exception?ex)
????????{
????????????throw?ex;
????????}
????????finally
????????{
????????????if?(sr?!=?null)
????????????{
????????????????sr.Close();
????????????????sr.Dispose();
????????????}
????????}
????}
????public?static?T?Deserialize<T>(string?XML,?Type[]?extraTypes)
????{
????????if?(XML?==?null?||?XML?==?string.Empty)
????????????return?default(T);
????????XmlSerializer?xs?=?null;
????????StringReader?sr?=?null;
????????try
????????{
????????????xs?=?new?XmlSerializer(typeof(T),?extraTypes);
????????????sr?=?new?StringReader(XML);
????????????return?(T)xs.Deserialize(sr);
????????}
????????catch?(Exception?ex)
????????{
????????????throw?ex;
????????}
????????finally
????????{
????????????if?(sr?!=?null)
????????????{
????????????????sr.Close();
????????????????sr.Dispose();
????????????}
????????}
????}
????public?static?void?SaveAs<T>(T?Obj,?string?FileName,?
???????????????????????Encoding?encoding,?Type[]?extraTypes)
????{
????????if?(File.Exists(FileName))
????????????File.Delete(FileName);
????????DirectoryInfo?di?=?new?DirectoryInfo(Path.GetDirectoryName(FileName));
????????if?(!di.Exists)
????????????di.Create();
????????XmlDocument?document?=?new?XmlDocument();
????????XmlWriterSettings?wSettings?=?new?XmlWriterSettings();
????????wSettings.Indent?=?true;
????????wSettings.Encoding?=?encoding;
????????wSettings.CloseOutput?=?true;
????????wSettings.CheckCharacters?=?false;
????????using?(XmlWriter?writer?=?XmlWriter.Create(FileName,?wSettings))
????????{
????????????if?(extraTypes?!=?null)
????????????????Serialize<T>(Obj,?writer,?extraTypes);
????????????else
????????????????Serialize<T>(Obj,?writer);
????????????writer.Flush();
????????????document.Save(writer);
????????}
????}
????public?static?void?SaveAs<T>(T?Obj,?string?FileName,?Type[]?extraTypes)
????{
????????SaveAs<T>(Obj,?FileName,?Encoding.UTF8,?extraTypes);
????}
????public?static?void?SaveAs<T>(T?Obj,?string?FileName,?Encoding?encoding)
????{
????????SaveAs<T>(Obj,?FileName,?encoding,?null);
????}
????public?static?void?SaveAs<T>(T?Obj,?string?FileName)
????{
????????SaveAs<T>(Obj,?FileName,?Encoding.UTF8);
????}
????public?static?T?Open<T>(string?FileName,?Type[]?extraTypes)
????{
????????T?obj?=?default(T);
????????if?(File.Exists(FileName))
????????{
????????????XmlReaderSettings?rSettings?=?new?XmlReaderSettings();
????????????rSettings.CloseInput?=?true;
????????????rSettings.CheckCharacters?=?false;
????????????using?(XmlReader?reader?=?XmlReader.Create(FileName,?rSettings))
????????????{
????????????????reader.ReadOuterXml();
????????????????if?(extraTypes?!=?null)
????????????????????obj?=?Deserialize<T>(reader,?extraTypes);
????????????????else
????????????????????obj?=?Deserialize<T>(reader);
????????????}
????????}
????????return?obj;
????}
????public?static?T?Open<T>(string?FileName)
????{
????????return?Open<T>(FileName,?null);
????}
}
?
????現在我們已經了解這個方法了,讓我們看看我們的問題所在。舉一個例子,我們有一個抽象類,Animal。然后有兩個繼承Animal的類:Human和Dog。
代碼 public?abstract?class?Animal
{
????public?abstract?int?Legs
????{
????????get;
????????set;
????}
????public?abstract?bool?HasTail
????{
????????get;
????????set;
????}
}
public?class?Human?:?Animal
{
????public?Human()
????{
????????this.Legs?=?2;
????????this.HasTail?=?false;
????}
????public?override?int?Legs
????{
????????get;
????????set;
????}
????public?override?bool?HasTail
????{
????????get;
????????set;
????}
}
public?class?Dog?:?Animal
{
????public?Dog()
????{
????????this.Legs?=?4;
????????this.HasTail?=?true;
????????this.Breed?=?"Black?Lab";
????}
????public?override?int?Legs
????{
????????get;
????????set;
????}
????public?override?bool?HasTail
????{
????????get;
????????set;
????}
????public?string?Breed
????{
????????get;
????????set;
????}
}
?
????現在我們有一個想要序列化的對象。它是HouseHold,它的有一個Animal集合屬性:
public?class?HouseHold{
????public?HouseHold()
????{
????????this.Residents?=?new?List<Animal>();
????}
????public?List<Animal>?Residents
????{
????????get;
????????set;
????}
}
?
?? 現在,我們序列化這個對象。
代碼 try{
????HouseHold?hh?=?new?HouseHold();
????hh.Residents.Add(new?Human());
????hh.Residents.Add(new?Human());
????hh.Residents.Add(new?Dog());
????string?xml?=?GenericSerializer.Serialize<HouseHold>(hh);
????Console.WriteLine(xml);
}
catch?(Exception?ex)
{
????Console.WriteLine(ex.ToString());
}
Console.Read();
?
我們將會得到下面的Exception的Message:
"生成 XML 文檔時出錯。?
下面是?InnerException的Message :
"不應是類型 Kirin.Human。使用 XmlInclude 或 SoapInclude 屬性靜態指定非已知的類型。"?
這里有個關鍵字“靜態”, 我們可以在每個類的頂部放置XmlInclude屬性解決這個問題,如:
代碼 ???[XmlInclude(typeof(Animal)),?XmlInclude(typeof(Human))]????public?class?HouseHold
????{
????????public?HouseHold()
????????{
????????????this.Residents?=?new?List<Animal>();
????????}
?????
????????public?List<Animal>?Residents
????????{
????????????get;
????????????set;
????????}
????}
?
? 但如果我們不知道的繼承Animal的所有類,如果我們的應用是可延展的,需要能夠使用由用戶自定義類型,上面的代碼是解決不了問題的。讓我們向下看,我會告訴你如何可以做到的。
?? 首先,我們要做的是使HouseHold類實現IXmlSerializable接口,這樣我們就可以攔截這個對象的序列化,我們自己去序列它。
? 接著,我們構建一個方法,能檢查所有的類型,在這個例子中,我們使用反射去查詢的所有繼承了Animal類的程序集。?
代碼 public?class?HouseHold?:?IXmlSerializable{
????private?static?Type[]?_animalTypes;
????static?HouseHold()
????{
????????_animalTypes?=?GetAnimalTypes().ToArray();
????}
????public?HouseHold()
????{
????????this.Residents?=?new?List<Animal>();
????}
????public?List<Animal>?Residents
????{
????????get;
????????set;
????}
????#region?IXmlSerializable?Members
????public?System.Xml.Schema.XmlSchema?GetSchema()
????{
????????return?null;
????}
????public?void?ReadXml(System.Xml.XmlReader?reader)
????{
????????bool?wasEmpty?=?reader.IsEmptyElement;
????????reader.Read();
????????if?(wasEmpty)
????????????return;
????????reader.MoveToContent();
????????reader.ReadStartElement("Residents");
????????this.Residents?=?GenericSerializer.Deserialize<List<Animal>>(reader,?_animalTypes);
????????reader.ReadEndElement();
????????//Read?Closing?Element
????????reader.ReadEndElement();
????}
????public?void?WriteXml(System.Xml.XmlWriter?writer)
????{
????????writer.WriteStartElement("Residents");
????????GenericSerializer.Serialize<List<Animal>>(this.Residents,?writer,?_animalTypes);
????????writer.WriteEndElement();
????}
????#endregion
????public?static?List<Type>?GetAnimalTypes()
????{
????????List<Type>?types?=?new?List<Type>();
????????Assembly?asm?=?typeof(HouseHold).Assembly;
????????Type?tAnimal?=?typeof(Animal);
????????//Query?our?types.?We?could?also?load?any?other?assemblies?and
????????//query?them?for?any?types?that?inherit?from?Animal
????????foreach?(Type?currType?in?asm.GetTypes())
????????{
????????if?(!currType.IsAbstract
????????????&&?!currType.IsInterface
????????????&&?tAnimal.IsAssignableFrom(currType))
????????????types.Add(currType);
????????}
????????return?types;
????}
}
?? ?現在,我們運行我們的測試代碼,能順利通過。希望對你有所幫助,謝謝!
轉載于:https://www.cnblogs.com/tangself/archive/2009/12/16/1625240.html
總結
以上是生活随笔為你收集整理的序列化包含多种不明类型的集合的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于多线程编程您不知道的 5 件事 有关
- 下一篇: 面板Ext.Panel使用