如何将字典序列化为XML文件?

问题描述:

我试图维护一个配置字典。如何将字典序列化为XML文件?

这是我的抽象类。

[Serializable] 
public abstract class Configuration 
{ 
} 

这里是一个具体的类(目前,我只有这个类)。

[Serializable] 
public class BinaryProblemConfiguration : Configuration 
{ 
    [XmlAttribute] 
    public decimal MinValue { get; set; } 
    [XmlAttribute] 
    public decimal MaxValue { get; set; } 
} 

我有一个类,其中包含Dictionary的配置级别。

  • 第一个参数是配置的名称。当name=""表示默认配置。
  • 等级表示困难。有三个级别:简单,中等和困难。
  • 第三个是配置。
/// <summary> 
/// The abstract level configuration allows descendent classes to configure themselves 
/// </summary> 
public abstract class LevelConfiguration 
{ 
    private Dictionary<string, Dictionary<Levels, Configuration>> _configurableLevels = new Dictionary<string, Dictionary<Levels, Configuration>>(); 

    /// <summary> 
    /// Adds a configurable level. 
    /// </summary> 
    /// <param name="level">The level to add.</param> 
    /// <param name="problemConfiguration">The problem configuration.</param> 
    protected void AddConfigurableLevel(string name, Levels level, Configuration problemConfiguration) 
    { 
     if (!_configurableLevels.ContainsKey(name)) 
     { 
      _configurableLevels.Add(name, new Dictionary<Levels, Configuration>()); 
     } 

     _configurableLevels[name].Add(level, problemConfiguration); 
    } 

    /// <summary> 
    /// Returns all the configurable levels. 
    /// </summary> 
    /// <param name="level"></param> 
    protected void RemoveConfigurableLevel(string name, Levels level) 
    { 
     _configurableLevels[name].Remove(level); 
    } 

    /// <summary> 
    /// Returns all the configurable names. 
    /// </summary> 
    /// <returns></returns> 
    public IEnumerable<string> GetConfigurationNames() 
    { 
     return _configurableLevels.Keys; 
    } 

    /// <summary> 
    /// Returns all the configurable levels. 
    /// </summary> 
    /// <returns></returns> 
    public IEnumerable<Levels> GetConfigurationLevels(string name) 
    { 
     return _configurableLevels[name].Keys; 
    } 

    /// <summary> 
    /// Gets the problem configuration for the specified level 
    /// </summary> 
    /// <param name="level">The level.</param> 
    /// <returns></returns> 
    public Configuration GetProblemConfiguration(string name, Levels level) 
    { 
     return _configurableLevels[name][level]; 
    } 
} 

这是创建一些配置中的类。我正在创建三个默认配置和两个习惯。

public class AdditionLevelConfiguration : LevelConfiguration 
{ 
    public AdditionLevelConfiguration() 
    { 
     AddConfigurableLevel("", Levels.Easy, GetEasyLevelConfiguration()); 
     AddConfigurableLevel("", Levels.Medium, GetMediumLevelConfiguration()); 
     AddConfigurableLevel("", Levels.Hard, GetHardLevelConfiguration()); 

     AddConfigurableLevel("config2", Levels.Easy, GetEasyLevelConfiguration()); 
     AddConfigurableLevel("config2", Levels.Medium, GetMediumLevelConfiguration()); 

     var configs = this.GetProblemConfiguration("config2", Levels.Medium); 
     var configs2 = this.GetProblemConfiguration("", Levels.Easy); 
    } 

    protected Configuration GetHardLevelConfiguration() 
    { 
     return new BinaryProblemConfiguration 
     { 
      MinValue = 100, 
      MaxValue = 1000, 
     }; 
    } 

    protected Configuration GetMediumLevelConfiguration() 
    { 
     return new BinaryProblemConfiguration 
     { 
      MinValue = 10, 
      MaxValue = 100, 
     }; 
    } 

    protected Configuration GetEasyLevelConfiguration() 
    { 
     return new BinaryProblemConfiguration 
     { 
      MinValue = 1, 
      MaxValue = 10, 
     }; 
    } 
} 

我打算将这些配置写入XML文件。我正在考虑将它们序列化,但它会引发一个错误。我该怎么办?

+1

Codereview用于获取工作代码的评论。 “我怎么做X”的问题属于Stack Overflow。 – sepp2k 2012-02-19 14:36:04

您可能会考虑的另一个选择是使用DataContractSerializer。我能够以这种方式序列化你的字典词典。

事情要记住,如果你走这条路线:

  • 您必须添加不同的属性。具体而言,您需要DataContract属性上的类型和DataMember。
  • 您需要确保所有属性都有setter,即使setter最终是私有的。
  • 创建DataContractSerializer时,需要确保知道您的所有类型。赋予它字典的类型可以处理字符串,级别和配置,而不是BinaryProblemConfiguration。附加的类型信息可以通过额外的构造函数重载提供。

例子:

var dict = new Dictionary<string,Dictionary<Levels,Configuration>>(); 
var wtr = XmlWriter.Create (Console.Out); 
var dcSerializer = new DataContractSerializer (dict.GetType(), new [] {typeof (BinaryProblemConfiguration)}); 
dcSerializer.WriteObject (wtr, dict); 

如果你做到上面,你也可以切换到DataContractJsonSerializer后更加紧凑JSON格式,如果你喜欢(假设XML不是硬性要求,当然)。

从我知道实现IDictionary的类不能被Xml序列化。 试试这个http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx,它为我工作。