zoukankan      html  css  js  c++  java
  • 序列化包含多种不明类型的集合

     代码:/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注入漏洞检测。

  • 相关阅读:
    Linux Shell编程入门
    vim 文件在linux不换行,只显示^M解决办法
    服务器高性能程序 磁盘I/O篇
    车牌识别_转自别人的博客
    ubuntu网络简单设置
    C++设计模式(转载)
    结构算法之道
    C++设计模式工厂方法
    二叉树的深度优先遍历、广度优先遍历和非递归遍历
    iptables
  • 原文地址:https://www.cnblogs.com/zhuqil/p/1624826.html
Copyright © 2011-2022 走看看