可序列化的泛型集合类
经常遇到集合类的序列化和反序列化,所以就有简化的想法,:)使用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
}
}
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
}
}
测试代码:
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:雪山飞狐;
附上使用该类生成的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> 谢谢
页:
[1]