导言:
你是否曾经想过序列化构造对象,它里面有一个集合,这个集合包含接口或者抽象类?你是否不知道所有的你要序列化的类型?好吧,如果这样,那么我可以帮助你。
使用代码:
让我们开始.首先,你将要将采用下面的帮助类,将它粘贴到你的项目之中。它将帮助你只用一行代码就能序列化一个对象为XML。
/// 一个用来序列化的通用类
/// </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 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 HouseHold()
{
this .Residents = new List < Animal > ();
}
public List < Animal > Residents
{
get ;
set ;
}
}
现在,我们序列化这个对象。
{
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:
下面是 InnerException的Message :
这里有个关键字“静态”, 我们可以在每个类的顶部放置XmlInclude属性解决这个问题,如:
public class HouseHold
{
public HouseHold()
{
this .Residents = new List < Animal > ();
}
public List < Animal > Residents
{
get ;
set ;
}
}
但如果我们不知道的继承Animal的所有类,如果我们的应用是可延展的,需要能够使用由用户自定义类型,上面的代码是解决不了问题的。让我们向下看,我会告诉你如何可以做到的。
首先,我们要做的是使HouseHold类实现IXmlSerializable接口,这样我们就可以拦截这个对象的序列化,我们自己去序列它。
接着,我们构建一个方法,能检查所有的类型,在这个例子中,我们使用反射去查询的所有继承了Animal类的程序集。
{
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网站安全吗?
如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!
快速了解HTTPS网站安全情况。
安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。
安装部署SSL证书变得更方便。
SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。
让服务器远离SSL证书漏洞侵扰
TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。