C# 类 XML 序列化基类
【转】http://blog.hetaoos.com/archives/34
有些时候,需要将一个类保存到文件用,C# 支持三种序列化:BinaryFormatter、SoapFormatter、XmlSerializer。
BinaryFormatter,不能手动修改数据,适合于 .NET 程序间交换数据。
SoapFormatter,可以手动修改数据,适合于 .NET 程序间交换数据。
XmlSerializer,这个可读性很强,适合于跨平台、跨语种交换数据,还可以用来保持配置文件。
XmlSerializer 的例子很多,可以参看MSDN上面的,这里就不再复制粘贴了。
由于某些项目的需要频繁使用XML交换数据,且类类型多样,如果每个都手动写代码转换,是很浪费时间的(虽然看上去代码很多,老板会认为有很多工作量。),所以写了一个模板类,以及 .NET 3.0 以后支持的扩展方法。
1 using System;
2 using System.Text;
3 using System.IO;
4 using System.Xml.Serialization;
5 using System.Diagnostics;
6 using System.Collections;
7 using System.Runtime.CompilerServices;
8
9 namespace com.hetaoos.Common.Utils
10 {
11 [Serializable]
12 public abstract class XmlSerializerBase<TClass>
13 where TClass : class
14 {
15
16 /// <summary>
17 /// 将该类转换为 XML 文本
18 /// </summary>
19 /// <returns></returns>
20 public string ToXmlString()
21 {
22 using (MemoryStream ms = new MemoryStream())
23 {
24 XmlSerializer serializer = GetXmlSerializer();
25 try
26 {
27 serializer.Serialize(ms, this);
28 ms.Close();
29 return Encoding.UTF8.GetString(ms.ToArray());
30 }
31 catch (Exception ex)
32 {
33 Debug.Print(ex.ToString());
34 return string.Empty;
35 }
36 }
37 }
38
39 /// <summary>
40 /// 保存当前对象到文件
41 /// </summary>
42 /// <param name="filePath"></param>
43 /// <returns></returns>
44 public bool WriteObjectToFile(string filePath)
45 {
46 try
47 {
48 File.WriteAllText(filePath, ToXmlString());
49 return true;
50 }
51 catch (Exception exc)
52 {
53 Debug.Print(exc.ToString());
54 return false;
55 }
56 }
57
58 /// <summary>
59 /// 从 XML 文件中还原对象
60 /// </summary>
61 /// <param name="filePath"></param>
62 /// <param name="type"></param>
63 /// <returns></returns>
64 public static object ReadObjectFromFile(string filePath, Type type)
65 {
66 try
67 {
68 return FromXmlString(File.ReadAllText(filePath), type);
69 }
70 catch (Exception exc)
71 {
72 Debug.Print(exc.ToString());
73 return null;
74 }
75 }
76
77 /// <summary>
78 /// 从 XML 字符串中还原对象
79 /// </summary>
80 /// <param name="xmlString"></param>
81 /// <returns></returns>
82 public static TClass FromXmlString(string xmlString)
83 {
84 return FromXmlString(xmlString, typeof(TClass)) as TClass;
85 }
86
87 /// <summary>
88 /// 将对象转换为 XML 字符串
89 /// </summary>
90 /// <param name="obj"></param>
91 /// <returns></returns>
92 public static string ToXmlString(TClass obj)
93 {
94 using (MemoryStream ms = new MemoryStream())
95 {
96 XmlSerializer serializer = GetXmlSerializer();
97 try
98 {
99 serializer.Serialize(ms, obj);
100 ms.Close();
101 return Encoding.UTF8.GetString(ms.ToArray());
102 }
103 catch (Exception ex)
104 {
105 Debug.Print(ex.ToString());
106 return string.Empty;
107 }
108 }
109 }
110
111 /// <summary>
112 /// 保存对象到文件
113 /// </summary>
114 /// <param name="filePath"></param>
115 /// <returns></returns>
116 public static bool WriteObjectToFile(TClass obj, string filePath)
117 {
118 try
119 {
120 File.WriteAllText(filePath, ToXmlString(obj));
121 return true;
122 }
123 catch (Exception exc)
124 {
125 Debug.Print(exc.ToString());
126 return false;
127 }
128 }
129 /// <summary>
130 /// 从 XML 文件中还原对象
131 /// </summary>
132 /// <param name="fileName"></param>
133 /// <returns></returns>
134 public static TClass ReadObjectFromFile(string fileName)
135 {
136 return ReadObjectFromFile(fileName, typeof(TClass)) as TClass;
137 }
138
139 /// <summary>
140 /// 从 XML 字符串中还原对象
141 /// </summary>
142 /// <param name="xmlString"></param>
143 /// <param name="type"></param>
144 /// <returns></returns>
145 public static object FromXmlString(string xmlString, Type type)
146 {
147 if (string.IsNullOrEmpty(xmlString))
148 {
149 return null;
150 }
151 using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
152 {
153 XmlSerializer serializer = GetXmlSerializer(type);
154 try
155 {
156 return serializer.Deserialize(stream);
157 }
158 catch
159 {
160 return null;
161 }
162 }
163
164 }
165
166 /// <summary>
167 /// 设置默认值
168 /// </summary>
169 public virtual void SetDefault()
170 {
171 }
172
173 private static Hashtable XmlSerializerCache = new Hashtable();
174 /// <summary>
175 /// 序列化转换器缓存,避免重复创建
176 /// </summary>
177 /// <param name="type"></param>
178 /// <returns></returns>
179 [MethodImpl(MethodImplOptions.Synchronized)]
180 public static XmlSerializer GetXmlSerializer(Type type)
181 {
182 lock (XmlSerializerCache)
183 {
184 XmlSerializer serializer = XmlSerializerCache[type] as XmlSerializer;
185 if (serializer == null)
186 {
187 serializer = new XmlSerializer(type);
188 XmlSerializerCache[type] = serializer;
189 }
190 return serializer;
191 }
192 }
193
194 /// <summary>
195 /// 获取当前类的序列话器
196 /// </summary>
197 /// <returns></returns>
198 public static XmlSerializer GetXmlSerializer()
199 {
200 return GetXmlSerializer(typeof(TClass));
201 }
202 }
203
204 #region 扩展类
205 public static class XmlSerializerEx
206 {
207 /// <summary>
208 /// 将对象转换为 XML 字符串
209 /// </summary>
210 /// <typeparam name="TClass"></typeparam>
211 /// <param name="t"></param>
212 /// <returns></returns>
213 public static string ToXmlString<TClass>(this TClass t)
214 where TClass : class
215 {
216 using (MemoryStream ms = new MemoryStream())
217 {
218 XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer();
219 try
220 {
221 serializer.Serialize(ms, t);
222 ms.Close();
223 return Encoding.UTF8.GetString(ms.ToArray());
224 }
225 catch (Exception ex)
226 {
227 Debug.Print(ex.ToString());
228 return string.Empty;
229 }
230 }
231 }
232
233 /// <summary>
234 /// 将 XML 字符串转换为对象
235 /// </summary>
236 /// <typeparam name="TClass"></typeparam>
237 /// <param name="t"></param>
238 /// <param name="xmlString"></param>
239 /// <returns></returns>
240 public static TClass FromXmlString<TClass>(this TClass t, string xmlString)
241 where TClass : class
242 {
243 if (string.IsNullOrEmpty(xmlString))
244 {
245 return null;
246 }
247 using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
248 {
249 XmlSerializer serializer = XmlSerializerBase<TClass>.GetXmlSerializer();
250 try
251 {
252 return serializer.Deserialize(stream) as TClass;
253 }
254 catch
255 {
256 return null;
257 }
258 }
259 }
260 }
261 #endregion
262 }
263
在需要XML序列化的类中,继承基类 XmlSerializerBase,即可。如
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Xml.Serialization;
5 using System.IO;
6
7 namespace com.hetaoos.Configurations
8 {
9 /// <summary>
10 /// 本地配置文件
11 /// </summary>
12 [DisplayName("本地配置文件")]
13 public class AppConfig : XmlSerializerBase<AppConfig>
14 {
15 /// <summary>
16 /// 遇到错误自动重启
17 /// </summary>
18 [XmlElement(ElementName = "OnErrorAutoReset")]
19 public bool OnErrorAutoReset { get; set; }
20
21 public AppConfig()
22 {
23
24 }
25
26 public override void SetDefault()
27 {
28 OnErrorAutoReset = true;
29 }
30
31 }
32 }
33
当然,如果目标类已经集成有一个基类了,可以使用静态方法,如:
1 //快速用法
2 AppConfig oldConfig = new AppConfig() { OnErrorAutoReset = true };
3 string xmlString = XmlSerializerBase<AppConfig>.ToXmlString(oldConfig);
4 AppConfig newConfig = XmlSerializerBase<AppConfig>.FromXmlString(xmlString);
5
6 //.NET 3.0 以后的扩展方法
7 xmlString = oldConfig.ToXmlString<AppConfig>();
8 //注意,这个返回的是一个新的对象,和 oldConfig 无关
9 newConfig = oldConfig.FromXmlString<AppConfig>(xmlString);
值得注意的是,在.NET 中创建的 序列化器 XmlSerializer 在使用结束后并其内部有个对象不会被销毁。也不清楚它什么时候会被销毁。目前观测到的结果是,显示调用垃圾回收方法GC.Collect(); 也不能将其销毁。
由于每种类型对应一个 XmlSerializer,但相同类型的对象来时,只要调用缓存中的序列化器,没有的时候才创建新的。于是,代码中加入了 序列化器缓存 XmlSerializerCache。