C# 类 XML 序列化基类
2010-12-02 17:05
197 查看
【转】http://blog.hetaoos.com/archives/34
有些时候,需要将一个类保存到文件用,C# 支持三种序列化:BinaryFormatter、SoapFormatter、XmlSerializer。
BinaryFormatter,不能手动修改数据,适合于 .NET 程序间交换数据。
SoapFormatter,可以手动修改数据,适合于 .NET 程序间交换数据。
XmlSerializer,这个可读性很强,适合于跨平台、跨语种交换数据,还可以用来保持配置文件。
XmlSerializer 的例子很多,可以参看MSDN上面的,这里就不再复制粘贴了。
由于某些项目的需要频繁使用XML交换数据,且类类型多样,如果每个都手动写代码转换,是很浪费时间的(虽然看上去代码很多,老板会认为有很多工作量。),所以写了一个模板类,以及 .NET 3.0 以后支持的扩展方法。
在需要XML序列化的类中,继承基类 XmlSerializerBase,即可。如
当然,如果目标类已经集成有一个基类了,可以使用静态方法,如:
值得注意的是,在.NET 中创建的 序列化器 XmlSerializer 在使用结束后并其内部有个对象不会被销毁。也不清楚它什么时候会被销毁。目前观测到的结果是,显示调用垃圾回收方法GC.Collect(); 也不能将其销毁。
由于每种类型对应一个 XmlSerializer,但相同类型的对象来时,只要调用缓存中的序列化器,没有的时候才创建新的。于是,代码中加入了 序列化器缓存 XmlSerializerCache。
有些时候,需要将一个类保存到文件用,C# 支持三种序列化:BinaryFormatter、SoapFormatter、XmlSerializer。
BinaryFormatter,不能手动修改数据,适合于 .NET 程序间交换数据。
SoapFormatter,可以手动修改数据,适合于 .NET 程序间交换数据。
XmlSerializer,这个可读性很强,适合于跨平台、跨语种交换数据,还可以用来保持配置文件。
XmlSerializer 的例子很多,可以参看MSDN上面的,这里就不再复制粘贴了。
由于某些项目的需要频繁使用XML交换数据,且类类型多样,如果每个都手动写代码转换,是很浪费时间的(虽然看上去代码很多,老板会认为有很多工作量。),所以写了一个模板类,以及 .NET 3.0 以后支持的扩展方法。
using System; using System.Text; using System.IO; using System.Xml.Serialization; using System.Diagnostics; using System.Collections; using System.Runtime.CompilerServices; namespace com.hetaoos.Common.Utils { [Serializable] public abstract class XmlSerializerBase<TClass> where TClass : class { /// <summary> /// 将该类转换为 XML 文本 /// </summary> /// <returns></returns> public string ToXmlString() { using (MemoryStream ms = new MemoryStream()) { XmlSerializer serializer = GetXmlSerializer(); try { serializer.Serialize(ms, this); ms.Close(); return Encoding.UTF8.GetString(ms.ToArray()); } catch (Exception ex) { Debug.Print(ex.ToString()); return string.Empty; } } } /// <summary> /// 保存当前对象到文件 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public bool WriteObjectToFile(string filePath) { try { File.WriteAllText(filePath, ToXmlString()); return true; } catch (Exception exc) { Debug.Print(exc.ToString()); return false; } } /// <summary> /// 从 XML 文件中还原对象 /// </summary> /// <param name="filePath"></param> /// <param name="type"></param> /// <returns></returns> public static object ReadObjectFromFile(string filePath, Type type) { try { return FromXmlString(File.ReadAllText(filePath), type); } catch (Exception exc) { Debug.Print(exc.ToString()); return null; } } /// <summary> /// 从 XML 字符串中还原对象 /// </summary> /// <param name="xmlString"></param> /// <returns></returns> public static TClass FromXmlString(string xmlString) { return FromXmlString(xmlString, typeof(TClass)) as TClass; } /// <summary> /// 将对象转换为 XML 字符串 /// </summary> /// <param name="obj"></param> /// <returns></returns> public static string ToXmlString(TClass obj) { using (MemoryStream ms = new MemoryStream()) { XmlSerializer serializer = GetXmlSerializer(); try { serializer.Serialize(ms, obj); ms.Close(); return Encoding.UTF8.GetString(ms.ToArray()); } catch (Exception ex) { Debug.Print(ex.ToString()); return string.Empty; } } } /// <summary> /// 保存对象到文件 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static bool WriteObjectToFile(TClass obj, string filePath) { try { File.WriteAllText(filePath, ToXmlString(obj)); return true; } catch (Exception exc) { Debug.Print(exc.ToString()); return false; } } /// <summary> /// 从 XML 文件中还原对象 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static TClass ReadObjectFromFile(string fileName) { return ReadObjectFromFile(fileName, typeof(TClass)) as TClass; } /// <summary> /// 从 XML 字符串中还原对象 /// </summary> /// <param name="xmlString"></param> /// <param name="type"></param> /// <returns></returns> public static object FromXmlString(string xmlString, Type type) { if (string.IsNullOrEmpty(xmlString)) { return null; } using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString))) { XmlSerializer serializer = GetXmlSerializer(type); try { return serializer.Deserialize(stream); } catch { return null; } } } /// <summary> /// 设置默认值 /// </summary> public virtual void SetDefault() { } private static Hashtable XmlSerializerCache = new Hashtable(); /// <summary> /// 序列化转换器缓存,避免重复创建 /// </summary> /// <param name="type"></param> /// <returns></returns> [MethodImpl(MethodImplOptions.Synchronized)] public static XmlSerializer GetXmlSerializer(Type type) { lock (XmlSerializerCache) { XmlSerializer serializer = XmlSerializerCache[type] as XmlSerializer; if (serializer == null) { serializer = new XmlSerializer(type); XmlSerializerCache[type] = serializer; } return serializer; } } /// <summary> /// 获取当前类的序列话器 /// </summary> /// <returns></returns> public static XmlSerializer GetXmlSerializer() { return GetXmlSerializer(typeof(TClass)); } } #region 扩展类 public static class XmlSerializerEx { /// <summary> /// 将对象转换为 XML 字符串 /// </summary> /// <typeparam name="TClass"></typeparam> /// <param name="t"></param> /// <returns></returns> public static string ToXmlString<TClass>(this TClass t) where TClass : class { using (MemoryStream ms = new MemoryStream()) { XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer(); try { serializer.Serialize(ms, t); ms.Close(); return Encoding.UTF8.GetString(ms.ToArray()); } catch (Exception ex) { Debug.Print(ex.ToString()); return string.Empty; } } } /// <summary> /// 将 XML 字符串转换为对象 /// </summary> /// <typeparam name="TClass"></typeparam> /// <param name="t"></param> /// <param name="xmlString"></param> /// <returns></returns> public static TClass FromXmlString<TClass>(this TClass t, string xmlString) where TClass : class { if (string.IsNullOrEmpty(xmlString)) { return null; } using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString))) { XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer(); try { return serializer.Deserialize(stream) as TClass; } catch { return null; } } } } #endregion }
在需要XML序列化的类中,继承基类 XmlSerializerBase,即可。如
using System; using System.Collections.Generic; using System.Text; using System.Xml.Serialization; using System.IO; namespace com.hetaoos.Configurations { /// <summary> /// 本地配置文件 /// </summary> [DisplayName("本地配置文件")] public class AppConfig : XmlSerializerBase<AppConfig> { /// <summary> /// 遇到错误自动重启 /// </summary> [XmlElement(ElementName = "OnErrorAutoReset")] public bool OnErrorAutoReset { get; set; } public AppConfig() { } public override void SetDefault() { OnErrorAutoReset = true; } } }
当然,如果目标类已经集成有一个基类了,可以使用静态方法,如:
//快速用法 AppConfig oldConfig = new AppConfig() { OnErrorAutoReset = true }; string xmlString = XmlSerializerBase<AppConfig>.ToXmlString(oldConfig); AppConfig newConfig = XmlSerializerBase<AppConfig>.FromXmlString(xmlString); //.NET 3.0 以后的扩展方法 xmlString = oldConfig.ToXmlString<AppConfig>(); //注意,这个返回的是一个新的对象,和 oldConfig 无关 newConfig = oldConfig.FromXmlString<AppConfig>(xmlString);
值得注意的是,在.NET 中创建的 序列化器 XmlSerializer 在使用结束后并其内部有个对象不会被销毁。也不清楚它什么时候会被销毁。目前观测到的结果是,显示调用垃圾回收方法GC.Collect(); 也不能将其销毁。
由于每种类型对应一个 XmlSerializer,但相同类型的对象来时,只要调用缓存中的序列化器,没有的时候才创建新的。于是,代码中加入了 序列化器缓存 XmlSerializerCache。
相关文章推荐
- c#中xml序列化 和binary 序列化
- C#温故而知新学习系列之XML编程—XmlSerializer类把对象序列化为XML文档(五)
- C#解析XML——使用属性控制XML序列化
- .NET(C#):XmlArrayItem特性和XmlElement特性在序列化数组的差别
- C#中的对象序列化成文本和XML案例
- C#实现XML与实体类之间相互转换的方法(序列化与反序列化)
- C#实现复杂XML的序列化与反序列化
- c# XML和实体类之间相互转换(序列化和反序列化)
- 关于C# XML序列化的一个BUG的修改
- c# XML和实体类之间相互转换(序列化和反序列化)
- C# 对象的xml序列化和反序列化
- C# XmlSerializer将对象序列化以及反序列化(Sqlite数据库)
- c# 对XML 解析 和 序列化
- .NET(C#):XML序列化时派生类的处理
- C#对象序列化XML时报错:反射类型XXX时出错
- C#.NET解析XML(使用属性控制 XML 序列化)
- C# XML序列化操作菜单
- c# xml序列化和反序列化
- c# 序列化对象为xml 方法
- 【C#】解决进行反序列化时出错:。InnerException 消息是“反序列化对象 属于类型 System.String 时出现错误。读取 XML 数据时,超出最大字符串内容长度配额 (8192)。