您的位置:首页 > 编程语言 > C#

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 以后支持的扩展方法。

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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: