明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 3615|回复: 4

[基础] 可序列化的泛型集合类

[复制链接]
发表于 2010-1-16 11:57 | 显示全部楼层 |阅读模式
经常遇到集合类的序列化和反序列化,所以就有简化的想法,:)
使用Xml序列化时集合类通常被序列化为数组,而忽视掉公共属性,但有时属性是必要了
  1. using System;
  2. using System.IO;
  3. using System.Xml;
  4. using System.Text;
  5. using System.Reflection;
  6. using System.Collections.Generic;
  7. using System.Xml.Serialization;
  8. using System.Runtime.Serialization;
  9. using System.Runtime.Serialization.Formatters.Binary;
  10. namespace TlsCad.Collections
  11. {
  12.     [Serializable]
  13.     public class SerialList<T> : List<T>
  14.     {
  15.         [NonSerialized]
  16.         public Action<T> ItemAdded;
  17.         [NonSerialized]
  18.         public Action<T> ItemRemoving;
  19.         public SerialList()
  20.             : base()
  21.         { }
  22.         public SerialList(IEnumerable<T> lst)
  23.             : base(lst)
  24.         { }
  25.         public virtual void CopyFrom(IEnumerable<T> lst)
  26.         {
  27.             base.AddRange(lst);
  28.             if (ItemAdded != null)
  29.             {
  30.                 foreach (T item in lst)
  31.                 {
  32.                     ItemAdded(item);
  33.                 }
  34.             }
  35.         }
  36.         #region List
  37.         public new virtual void Add(T item)
  38.         {
  39.             base.Add(item);
  40.             if (ItemAdded != null)
  41.             {
  42.                 ItemAdded(item);
  43.             }
  44.         }
  45.         public new virtual void AddRange(IEnumerable<T> items)
  46.         {
  47.             base.AddRange(items);
  48.             if (ItemAdded != null)
  49.             {
  50.                 foreach (T item in items)
  51.                 {
  52.                     ItemAdded(item);
  53.                 }
  54.             }
  55.         }
  56.         public new virtual bool Remove(T item)
  57.         {
  58.             if (ItemRemoving != null && this.Contains(item))
  59.             {
  60.                 ItemRemoving(item);
  61.             }
  62.             return base.Remove(item);
  63.         }
  64.         public new virtual void RemoveRange(int index, int count)
  65.         {
  66.             if (ItemRemoving != null)
  67.             {
  68.                 for (int i = index; i < Count && i < index + count; i++)
  69.                 {
  70.                     ItemRemoving(this[i]);
  71.                 }
  72.             }
  73.             base.RemoveRange(index, count);
  74.         }
  75.         public new virtual void RemoveAt(int index)
  76.         {
  77.             if (ItemRemoving != null && index > 0 && index < Count)
  78.             {
  79.                 ItemRemoving(this[index]);
  80.             }
  81.             base.RemoveAt(index);
  82.         }
  83.         #endregion
  84.         #region Xml
  85.         public virtual void WriteXml(string path)
  86.         {
  87.             using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
  88.             {
  89.                 XmlSerializer xs = new XmlSerializer(GetType());
  90.                 xs.Serialize(writer, this);
  91.             }
  92.         }
  93.         public virtual SerialList<T> ReadXml(string path)
  94.         {
  95.             if (File.Exists(path))
  96.             {
  97.                 using (XmlTextReader reader = new XmlTextReader(path))
  98.                 {
  99.                     reader.Normalization = false;
  100.                     XmlSerializer xs = new XmlSerializer(GetType());
  101.                     SerialList<T> items = ((SerialList<T>)xs.Deserialize(reader));
  102.                     CopyFrom(items);
  103.                     return items;
  104.                 }
  105.             }
  106.             return null;
  107.         }
  108.         #endregion
  109.         #region Bin
  110.         class UBinder : SerializationBinder
  111.         {
  112.             public override Type BindToType(string assemblyName, string typeName)
  113.             {
  114.                 try
  115.                 {
  116.                     return Type.GetType(typeName);
  117.                 }
  118.                 catch
  119.                 {
  120.                     return Assembly.Load(assemblyName).GetType(typeName);
  121.                 }
  122.             }
  123.         }
  124.         public virtual void WriteTo(string path)
  125.         {
  126.             using (Stream stream = File.Open(path, FileMode.Create))
  127.             {
  128.                 BinaryFormatter bformatter = new BinaryFormatter();
  129.                 bformatter.Serialize(stream, this);
  130.             }
  131.         }
  132.         public virtual SerialList<T> ReadFrom(string path)
  133.         {
  134.             if (File.Exists(path))
  135.             {
  136.                 using (Stream stream = File.Open(path, FileMode.Open))
  137.                 {
  138.                     BinaryFormatter bformatter = new BinaryFormatter();
  139.                     bformatter.Binder = new UBinder();
  140.                     SerialList<T> lst = (SerialList<T>)bformatter.Deserialize(stream);
  141.                     CopyFrom(lst);
  142.                     return lst;
  143.                 }
  144.             }
  145.             return null;
  146.         }
  147.         #endregion
  148.     }
  149. }

评分

参与人数 1威望 +1 明经币 +2 金钱 +20 贡献 +5 激情 +5 收起 理由
ahlzl + 1 + 2 + 20 + 5 + 5 【精华】好程序

查看全部评分

 楼主| 发表于 2010-1-16 11:58 | 显示全部楼层
  1. using System;
  2. using System.IO;
  3. using System.Xml;
  4. using System.Text;
  5. using System.Linq;
  6. using System.Xml.Serialization;
  7. using System.Collections.Generic;
  8. using System.Runtime.Serialization;
  9. using System.Runtime.Serialization.Formatters.Binary;
  10. namespace TlsCad.Collections
  11. {
  12.     [Serializable]
  13.     public class SerialList<TInfo, TValue> : SerialList<TValue>
  14.     {
  15.         public TInfo Info { get; set; }
  16.         public SerialList()
  17.             : base()
  18.         { }
  19.         public SerialList(IEnumerable<TValue> lst)
  20.             : base(lst)
  21.         { }
  22.         public virtual void CopyFrom(SerialList<TInfo, TValue> lst)
  23.         {
  24.             Info = lst.Info;
  25.             base.CopyFrom(lst);
  26.         }
  27.         
  28.         #region Xml
  29.         public new virtual void WriteXml(string path)
  30.         {
  31.             XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
  32.             ns.Add("", "");
  33.             using (XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8))
  34.             {
  35.                 writer.WriteStartDocument();
  36.                 writer.WriteStartElement("SerialList");
  37.                 writer.WriteStartElement("Info");
  38.                 XmlSerializer xs = new XmlSerializer(typeof(TInfo));
  39.                 xs.Serialize(writer, Info, ns);
  40.                 writer.WriteEndElement();
  41.                 writer.WriteStartElement("Values");
  42.                 xs = new XmlSerializer(typeof(TValue));
  43.                 foreach (TValue item in this)
  44.                 {
  45.                     xs.Serialize(writer, item, ns);
  46.                 }
  47.                 writer.WriteEndElement();
  48.                 writer.WriteEndElement();
  49.                 writer.Close();
  50.             }
  51.         }
  52.         public new virtual SerialList<TInfo, TValue> ReadXml(string path)
  53.         {
  54.             if (File.Exists(path))
  55.             {
  56.                 using (XmlTextReader reader = new XmlTextReader(path))
  57.                 {
  58.                     SerialList<TInfo, TValue> lst = new SerialList<TInfo, TValue>();
  59.                     reader.Normalization = false;
  60.                     reader.ReadToDescendant("Info");
  61.                     reader.Read();
  62.                     XmlSerializer xs = new XmlSerializer(typeof(TInfo));
  63.                     lst.Info = (TInfo)xs.Deserialize(reader);
  64.                     reader.Read();
  65.                     reader.Read();
  66.                     xs = new XmlSerializer(typeof(TValue));
  67.                     while (reader.NodeType != XmlNodeType.EndElement)
  68.                     {
  69.                         TValue item = (TValue)xs.Deserialize(reader);
  70.                         if (item != null)
  71.                         {
  72.                             lst.Add(item);
  73.                         }
  74.                     };
  75.                     reader.Close();
  76.                     CopyFrom(lst);
  77.                     return lst;
  78.                 }
  79.             }
  80.             return null;
  81.         }
  82.         #endregion
  83.         #region Bin
  84.         public new virtual SerialList<TInfo, TValue> ReadFrom(string path)
  85.         {
  86.             SerialList<TInfo, TValue> lst =
  87.                 (SerialList<TInfo, TValue>)base.ReadFrom(path);
  88.             if (lst != null)
  89.             {
  90.                 Info = lst.Info;
  91.             }
  92.             return lst;
  93.         }
  94.         #endregion
  95.     }
  96. }
 楼主| 发表于 2010-1-16 11:59 | 显示全部楼层
测试代码:
  1.         [Serializable]
  2.         public struct MyInfo : IFormattable
  3.         {
  4.             public string name;
  5.             public string des;
  6.             #region IFormattable 成员
  7.             string IFormattable.ToString(string format, IFormatProvider formatProvider)
  8.             {
  9.                 return string.Format("name:{0},des:{1}", name, des);
  10.             }
  11.             #endregion
  12.         }
  13.         
  14.         [Serializable]
  15.         public struct MyValue : IFormattable
  16.         {
  17.             public string key;
  18.             public string name;
  19.             #region IFormattable 成员
  20.             string IFormattable.ToString(string format, IFormatProvider formatProvider)
  21.             {
  22.                 return string.Format("key:{0},name:{1};", key, name);
  23.             }
  24.             #endregion
  25.         }
  26.         [CommandMethod("tt")]
  27.         public static void Test()
  28.         {
  29.             SerialList<MyInfo, MyValue> lst =
  30.                 new SerialList<MyInfo, MyValue>();
  31.             lst.ItemAdded = i => Helper.Editor.WriteMessage("\nAdd a item:{0}", i);
  32.             lst.Add(new MyValue { name = "lzh", key = "1" });
  33.             lst.Add(new MyValue { name = "雪山飞狐", key = "2" });
  34.             lst.Info = new MyInfo { name = "TlsCad", des = "This is a test" };
  35.             lst.WriteTo("d:\\1.bin");
  36.             lst.WriteXml("d:\\2.xml");
  37.             SerialList<MyInfo, MyValue> lst2 =
  38.                 new SerialList<MyInfo, MyValue>();
  39.             lst2.ReadFrom("d:\\1.bin");
  40.             Helper.Editor.WriteMessage("\ninfo from Bin:{0}", lst2.Info);
  41.             foreach (MyValue s in lst2)
  42.             {
  43.                 Helper.Editor.WriteMessage("\n{0}", s);
  44.             }
  45.             SerialList<MyInfo, MyValue> lst3 =
  46.                 new SerialList<MyInfo, MyValue>();
  47.             lst3.ReadXml("d:\\2.xml");
  48.             Helper.Editor.WriteMessage("\ninfo from Xml:{0}", lst3.Info);
  49.             foreach (MyValue s in lst3)
  50.             {
  51.                 Helper.Editor.WriteMessage("\n{0}", s);
  52.             }
  53.         }
复制代码
命令行输出:
命令: 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:雪山飞狐;
 楼主| 发表于 2010-1-18 15:15 | 显示全部楼层
附上使用该类生成的xml文档(NetAutoLoad中使用的初始化文件)
  1. <?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
  2. How to:
  3. 1.第一次运行时,用NetLoad命令加载;
  4. 2.下次运行时程序将自动加载.
  5. 注意:
  6. 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.添加/删除程序集
  7. 2.设置程序集启动方式
  8. 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>
复制代码
发表于 2010-6-6 18:34 | 显示全部楼层
谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-29 00:08 , Processed in 0.631705 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表