如何读取自定义配置对象列表

时间:2010-06-06 14:01:44

标签: c# configuration app-config

我想在稍微不同的场景中实现Craig Andera's custom XML configuration handler。我想要做的是读入定义为:

的任意长度的自定义对象列表
public class TextFileInfo
{
    public string Name { get; set; }
    public string TextFilePath { get; set; }
    public string XmlFilePath { get; set; }
}

我设法为一个自定义对象复制了Craig的解决方案但是如果我想要几个呢?

Craig的反序列化代码是:

public class XmlSerializerSectionHandler : IConfigurationSectionHandler
{
    public object Create(object parent, object configContext, XmlNode section)
    {
        XPathNavigator nav = section.CreateNavigator();
        string typename = (string)nav.Evaluate("string(@type)");
        Type t = Type.GetType(typename);
        XmlSerializer ser = new XmlSerializer(t);
        return ser.Deserialize(new XmlNodeReader(section));
    }
}

我想我能做到这一点,如果我能得到

Type t = Type.GetType("System.Collections.Generic.List<TextFileInfo>")

工作,但它抛出

Could not load type 'System.Collections.Generic.List<Test1.TextFileInfo>' from assembly 'Test1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

1 个答案:

答案 0 :(得分:5)

我不认为这会在那种情况下起作用。 Craig的解决方案适用于简单的对象图,但集合有点棘手。列表被序列化为数组,因此将示例放入序列化列表中就像:

<ArrayOfTextFileInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlsns:xsd="http://www.w3.org/2001/XMLSchema>
  <TextFileInfo>
    <Name>My Text File</Name>
    <TextFilePath>C:\MyTextFile.txt</TextFilePath>
    <XmlFilePath>C:\MyXmlFile.xml</XmlFilePath>
  </TextFileInfo>
</ArrayOfTextFileInfo>

现在,我猜你可以把它放在配置中,只要配置部分命名为“ArrayOfTextFileInfo”。不完全那么友好。我认为您应该做的是使用标准配置类来构建它:

public class TextFileConfigurationElement : ConfigurationElement
{
  [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
  public string Name { 
    get { return (string)this["name"]; }
    set { this["name"] = value; }
  }

  [ConfigurationProperty("textFilePath")]
  public string TextFilePath {
    get { return (string)this["textFilePath"]; }
    set { this["textFilePath"] = value; }
  }

  [ConfigurationProperty("xmlFilePath")]
  public string XmlFilePath {
    get { return (string)this["xmlFilePath"]; }
    set { this["xmlFilePath"] = value; }
  }
}

[ConfigurationCollection(typeof(TextFileConfigurationElement))]
public class TextFileConfigurationElementCollection : ConfigurationElementCollection
{
  protected override void CreateNewElement() {
    return new TextFileConfigurationElement();
  }

  protected override object GetElementKey(ConfigurationElement element) {
    return ((TextFileConfigurationElement)element).Name;
  }
}

public class TextFilesConfigurationSection : ConfigurationSection
{
  [ConfigurationProperty("files")]
  public TextFileConfigurationElementCollection Files {
    get { return (TextFileConfigurationElementCollection)this["files"]; }
    set { this["files"] = value; }
  }

  public static TextFilesConfigurationSection GetInstance() {
    return ConfigurationManager.GetSection("textFiles") as TextFilesConfigurationSection;
  }
}

注册配置部分后:

<configSections>
  <add name="textFiles" type="...{type here}..." />
</configSections>

您可以添加配置:

<textFiles>
  <files>
    <add name="File01" textFilePath="C:\File01.txt" xmlTextFile="C:\File01.xml" />
  </files>
</textFiles>

在代码中使用它:

public List<TextFileInfo> GetFiles() {
  var list = new List<TextFileInfo>();

  var config = TextFileConfigurationSection.GetInstance();
  if (config == null)
    return list;

  foreach (TextFileConfigurationElement fileConfig in config.Files) {
    list.Add(new TextFileInfo 
                        {
                          Name = fileConfig.Name,
                          TextFilePath = fileConfig.TextFilePath,
                          XmlFilePath = fileConfig.XmlFilePath
                         });

  }

  return list;
}

另外,这个:

Type t = Type.GetType("System.Collections.Generic.List<TextFileInfo>")

由于几个原因无法工作,你还没有完全限定TextFileInfo类型(需要命名空间),并且你对泛型类型的定义是错误的(我可以看到为什么你没有这样指定它),它应该看起来像:

Type t = Type.GetType("System.Collections.Generic.List`1[MyNamespace.TextFileInfo]");

希望有所帮助!