雪山飞狐_lzh 发表于 2010-1-16 11:57:00

可序列化的泛型集合类

经常遇到集合类的序列化和反序列化,所以就有简化的想法,:)
使用Xml序列化时集合类通常被序列化为数组,而忽视掉公共属性,但有时属性是必要了
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Reflection;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace TlsCad.Collections
{
   
    public class SerialList<T> : List<T>
    {
      
      public Action<T> ItemAdded;
      
      public Action<T> ItemRemoving;
      public SerialList()
            : base()
      { }
      public SerialList(IEnumerable<T> lst)
            : base(lst)
      { }
      public virtual void CopyFrom(IEnumerable<T> lst)
      {
            base.AddRange(lst);
            if (ItemAdded != null)
            {
                foreach (T item in lst)
                {
                  ItemAdded(item);
                }
            }
      }
      #region List
      public new virtual void Add(T item)
      {
            base.Add(item);
            if (ItemAdded != null)
            {
                ItemAdded(item);
            }
      }
      public new virtual void AddRange(IEnumerable<T> items)
      {
            base.AddRange(items);
            if (ItemAdded != null)
            {
                foreach (T item in items)
                {
                  ItemAdded(item);
                }
            }
      }
      public new virtual bool Remove(T item)
      {
            if (ItemRemoving != null && this.Contains(item))
            {
                ItemRemoving(item);
            }
            return base.Remove(item);
      }
      public new virtual void RemoveRange(int index, int count)
      {
            if (ItemRemoving != null)
            {
                for (int i = index; i < Count && i < index + count; i++)
                {
                  ItemRemoving(this);
                }
            }
            base.RemoveRange(index, count);
      }
      public new virtual void RemoveAt(int index)
      {
            if (ItemRemoving != null && index > 0 && index < Count)
            {
                ItemRemoving(this);
            }
            base.RemoveAt(index);
      }
      #endregion
      #region Xml
      public virtual void WriteXml(string path)
      {
            using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
            {
                XmlSerializer xs = new XmlSerializer(GetType());
                xs.Serialize(writer, this);
            }
      }
      public virtual SerialList<T> ReadXml(string path)
      {
            if (File.Exists(path))
            {
                using (XmlTextReader reader = new XmlTextReader(path))
                {
                  reader.Normalization = false;
                  XmlSerializer xs = new XmlSerializer(GetType());
                  SerialList<T> items = ((SerialList<T>)xs.Deserialize(reader));
                  CopyFrom(items);
                  return items;
                }
            }
            return null;
      }
      #endregion
      #region Bin
      class UBinder : SerializationBinder
      {
            public override Type BindToType(string assemblyName, string typeName)
            {
                try
                {
                  return Type.GetType(typeName);
                }
                catch
                {
                  return Assembly.Load(assemblyName).GetType(typeName);
                }
            }
      }
      public virtual void WriteTo(string path)
      {
            using (Stream stream = File.Open(path, FileMode.Create))
            {
                BinaryFormatter bformatter = new BinaryFormatter();
                bformatter.Serialize(stream, this);
            }
      }
      public virtual SerialList<T> ReadFrom(string path)
      {
            if (File.Exists(path))
            {
                using (Stream stream = File.Open(path, FileMode.Open))
                {
                  BinaryFormatter bformatter = new BinaryFormatter();
                  bformatter.Binder = new UBinder();
                  SerialList<T> lst = (SerialList<T>)bformatter.Deserialize(stream);
                  CopyFrom(lst);
                  return lst;
                }
            }
            return null;
      }
      #endregion
    }

}

雪山飞狐_lzh 发表于 2010-1-16 11:58:00

using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Linq;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace TlsCad.Collections
{
   
    public class SerialList<TInfo, TValue> : SerialList<TValue>
    {
      public TInfo Info { get; set; }
      public SerialList()
            : base()
      { }
      public SerialList(IEnumerable<TValue> lst)
            : base(lst)
      { }
      public virtual void CopyFrom(SerialList<TInfo, TValue> lst)
      {
            Info = lst.Info;
            base.CopyFrom(lst);
      }
      
      #region Xml
      public new virtual void WriteXml(string path)
      {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("SerialList");
                writer.WriteStartElement("Info");
                XmlSerializer xs = new XmlSerializer(typeof(TInfo));
                xs.Serialize(writer, Info, ns);
                writer.WriteEndElement();
                writer.WriteStartElement("Values");
                xs = new XmlSerializer(typeof(TValue));
                foreach (TValue item in this)
                {
                  xs.Serialize(writer, item, ns);
                }
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.Close();
            }
      }
      public new virtual SerialList<TInfo, TValue> ReadXml(string path)
      {
            if (File.Exists(path))
            {
                using (XmlTextReader reader = new XmlTextReader(path))
                {
                  SerialList<TInfo, TValue> lst = new SerialList<TInfo, TValue>();
                  reader.Normalization = false;
                  reader.ReadToDescendant("Info");
                  reader.Read();
                  XmlSerializer xs = new XmlSerializer(typeof(TInfo));
                  lst.Info = (TInfo)xs.Deserialize(reader);
                  reader.Read();
                  reader.Read();
                  xs = new XmlSerializer(typeof(TValue));
                  while (reader.NodeType != XmlNodeType.EndElement)
                  {
                        TValue item = (TValue)xs.Deserialize(reader);
                        if (item != null)
                        {
                            lst.Add(item);
                        }
                  };
                  reader.Close();
                  CopyFrom(lst);
                  return lst;
                }
            }
            return null;
      }
      #endregion
      #region Bin
      public new virtual SerialList<TInfo, TValue> ReadFrom(string path)
      {
            SerialList<TInfo, TValue> lst =
                (SerialList<TInfo, TValue>)base.ReadFrom(path);
            if (lst != null)
            {
                Info = lst.Info;
            }
            return lst;
      }
      #endregion
    }
}

雪山飞狐_lzh 发表于 2010-1-16 11:59:00

测试代码:
      
      public struct MyInfo : IFormattable
      {
            public string name;
            public string des;
            #region IFormattable 成员
            string IFormattable.ToString(string format, IFormatProvider formatProvider)
            {
                return string.Format("name:{0},des:{1}", name, des);
            }
            #endregion
      }
      
      
      public struct MyValue : IFormattable
      {
            public string key;
            public string name;
            #region IFormattable 成员
            string IFormattable.ToString(string format, IFormatProvider formatProvider)
            {
                return string.Format("key:{0},name:{1};", key, name);
            }
            #endregion
      }
      
      public static void Test()
      {
            SerialList<MyInfo, MyValue> lst =
                new SerialList<MyInfo, MyValue>();
            lst.ItemAdded = i => Helper.Editor.WriteMessage("\nAdd a item:{0}", i);
            lst.Add(new MyValue { name = "lzh", key = "1" });
            lst.Add(new MyValue { name = "雪山飞狐", key = "2" });
            lst.Info = new MyInfo { name = "TlsCad", des = "This is a test" };
            lst.WriteTo("d:\\1.bin");
            lst.WriteXml("d:\\2.xml");
            SerialList<MyInfo, MyValue> lst2 =
                new SerialList<MyInfo, MyValue>();
            lst2.ReadFrom("d:\\1.bin");
            Helper.Editor.WriteMessage("\ninfo from Bin:{0}", lst2.Info);
            foreach (MyValue s in lst2)
            {
                Helper.Editor.WriteMessage("\n{0}", s);
            }
            SerialList<MyInfo, MyValue> lst3 =
                new SerialList<MyInfo, MyValue>();
            lst3.ReadXml("d:\\2.xml");
            Helper.Editor.WriteMessage("\ninfo from Xml:{0}", lst3.Info);
            foreach (MyValue s in lst3)
            {
                Helper.Editor.WriteMessage("\n{0}", s);
            }
      }命令行输出:
命令: tt
Add a item:key:1,name:lzh;
Add a item:key:2,name:雪山飞狐;
info from Bin:name:TlsCad,des:This is a test
key:1,name:lzh;
key:2,name:雪山飞狐;
info from Xml:name:TlsCad,des:This is a test
key:1,name:lzh;
key:2,name:雪山飞狐;

雪山飞狐_lzh 发表于 2010-1-18 15:15:00

附上使用该类生成的xml文档(NetAutoLoad中使用的初始化文件)
<?xml version="1.0" encoding="utf-8"?><SerialList><Info><AssemInfo><Name>NetAutoLoad</Name><Fullname>NetAutoLoad, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null</Fullname><Loader>D:\TlsCad\Bin\NetAutoLoad.dll</Loader><LoadType>LoadByCmd</LoadType><Description>NetAutoLoad For AutoCad
How to:
1.第一次运行时,用NetLoad命令加载;
2.下次运行时程序将自动加载.
注意:
1.Ass是命令列表文件,包含程序说明和命令说明,可覆盖.</Description></AssemInfo></Info><Values><Command><GlobalName>Nal:C</GlobalName><LocalizedName>Nal:C</LocalizedName><GroupName>TlsCad_Nal</GroupName><TypeName>TlsCad.NetAutoLoad.TlsMain</TypeName><MethodName>ShowCmds</MethodName><Description>命令行显示命令列表</Description></Command><Command><GlobalName>Nal:L</GlobalName><LocalizedName>Nal:L</LocalizedName><GroupName>TlsCad_Nal</GroupName><TypeName>TlsCad.NetAutoLoad.TlsMain</TypeName><MethodName>NetLoad</MethodName><Description>加载程序集</Description></Command><Command><GlobalName>Nal:M</GlobalName><LocalizedName>Nal:M</LocalizedName><GroupName>TlsCad_Nal</GroupName><TypeName>TlsCad.NetAutoLoad.TlsMain</TypeName><MethodName>Manage</MethodName><Description>1.添加/删除程序集
2.设置程序集启动方式
3.为命令添加帮助</Description></Command><Command><GlobalName>Nal:U</GlobalName><LocalizedName>Nal:U</LocalizedName><GroupName>TlsCad_Nal</GroupName><TypeName>TlsCad.NetAutoLoad.TlsMain</TypeName><MethodName>UnReg</MethodName><Description>程序卸载</Description></Command></Values></SerialList>

hmxmylove 发表于 2010-6-6 18:34:00

谢谢
页: [1]
查看完整版本: 可序列化的泛型集合类