在项目中需要一个Dictionary来保存键值对,类型为Dictionary<string,List<string>>,在向文件流中序列化的时候出现了错误,查询资料发现.net中的XmlSerializer不支持Dictionary,网上有很多应对方案,但都比较复杂,用起来总觉得心里不够踏实(害怕BUG),下面从另一个角度,在序列化和反序列化的时候进行数据类型的转换,从而达到序列化的目的,示例代码如下:
经测试,可以正常工作,这里我们实际上采用了目标转换的手法,将待序列化的对象转换为自定义的支持序列化的类型,在反序列化的时候首先反序列化为自定义的对象类型,然后再构造最终对象。
个人觉得微软应该针对Dictionary添加XML序列化支持,因为它的数据结构可以很轻易的映射到XML文档中:键值映射为一个节点,该键值对应的对象映射为此节点的子节点。
/// <summary>
/// This class is used for xml serialization on generic type Dictionary
/// </summary>
public class DictionaryHolder
{
public string logicalName = "";
public List<string> physicalNames = new List<string>();
}
/// <summary>
/// Loads the specified database.
/// </summary>
/// <param name="database">The database.</param>
public void load(string database)
{
FileStream fs = null;
try
{
XmlSerializer xs = new XmlSerializer(typeof(List<DictionaryHolder>));
fs = new FileStream(database, FileMode.Open, FileAccess.Read, FileShare.Read);
List<DictionaryHolder> holders = (List<DictionaryHolder>)xs.Deserialize(fs);
this._dictionary.Clear();
foreach (DictionaryHolder holder in holders)
{
this._dictionary.Add(holder.logicalName, holder.physicalNames);
}
}
catch(Exception ex)
{
throw;
}
finally
{
if (fs != null)
fs.Close();
}
}
/// <summary>
/// Saves the specified database.
/// </summary>
/// <param name="database">The database.</param>
public void save(string database)
{
FileStream fs = null;
try
{
List<DictionaryHolder> holders = new List<DictionaryHolder>();
foreach (string key in this._dictionary.Keys)
{
DictionaryHolder holder = new DictionaryHolder();
holder.logicalName = key;
holder.physicalNames = this._dictionary[key];
holders.Add(holder);
}
XmlSerializer xs = new XmlSerializer(typeof(List<DictionaryHolder>));
fs = new FileStream(database, FileMode.Create, FileAccess.Write, FileShare.Read);
xs.Serialize(fs, holders);
}
catch (Exception ex)
{
throw;
}
finally
{
if (fs != null)
fs.Close();
}
}
/// This class is used for xml serialization on generic type Dictionary
/// </summary>
public class DictionaryHolder
{
public string logicalName = "";
public List<string> physicalNames = new List<string>();
}
/// <summary>
/// Loads the specified database.
/// </summary>
/// <param name="database">The database.</param>
public void load(string database)
{
FileStream fs = null;
try
{
XmlSerializer xs = new XmlSerializer(typeof(List<DictionaryHolder>));
fs = new FileStream(database, FileMode.Open, FileAccess.Read, FileShare.Read);
List<DictionaryHolder> holders = (List<DictionaryHolder>)xs.Deserialize(fs);
this._dictionary.Clear();
foreach (DictionaryHolder holder in holders)
{
this._dictionary.Add(holder.logicalName, holder.physicalNames);
}
}
catch(Exception ex)
{
throw;
}
finally
{
if (fs != null)
fs.Close();
}
}
/// <summary>
/// Saves the specified database.
/// </summary>
/// <param name="database">The database.</param>
public void save(string database)
{
FileStream fs = null;
try
{
List<DictionaryHolder> holders = new List<DictionaryHolder>();
foreach (string key in this._dictionary.Keys)
{
DictionaryHolder holder = new DictionaryHolder();
holder.logicalName = key;
holder.physicalNames = this._dictionary[key];
holders.Add(holder);
}
XmlSerializer xs = new XmlSerializer(typeof(List<DictionaryHolder>));
fs = new FileStream(database, FileMode.Create, FileAccess.Write, FileShare.Read);
xs.Serialize(fs, holders);
}
catch (Exception ex)
{
throw;
}
finally
{
if (fs != null)
fs.Close();
}
}
经测试,可以正常工作,这里我们实际上采用了目标转换的手法,将待序列化的对象转换为自定义的支持序列化的类型,在反序列化的时候首先反序列化为自定义的对象类型,然后再构造最终对象。
个人觉得微软应该针对Dictionary添加XML序列化支持,因为它的数据结构可以很轻易的映射到XML文档中:键值映射为一个节点,该键值对应的对象映射为此节点的子节点。