序列化包含多种不明类型的集合

 代码:/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网站安全吗?

如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!

SSL检测评估

快速了解HTTPS网站安全情况。

安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。

SSL证书工具

安装部署SSL证书变得更方便。

SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。

SSL漏洞检测

让服务器远离SSL证书漏洞侵扰

TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。

转载于:https://www.cnblogs.com/zhuqil/archive/2009/12/15/1624826.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值