关于C#:自定义app.config部分,包含一个简单的”add”元素列表

Custom app.config section with a simple list of “add” elements

如何创建一个自定义app.config节,它只是一个简单的add元素列表?

我找到了几个例子(例如,如何在app.config中创建自定义配置节?)对于如下所示的自定义节:

1
2
3
4
5
6
<RegisterCompanies>
  <Companies>
    <Company name="Tata Motors" code="Tata"/>
    <Company name="Honda Motors" code="Honda"/>
  </Companies>
</RegisterCompanies>

但如何避免额外的收集元素("公司"),使其看起来与appSettingsconnectionStrings部分相同?换句话说,我想:

1
2
3
4
<registerCompanies>
 
 
</registerCompanies>


基于op-config文件的代码的完整示例:

1
2
3
4
5
6
7
8
9
10
<configuration>
    <configSections>
        <section name="registerCompanies"
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
       
       
    </registerCompanies>
</configuration>

下面是实现具有折叠集合的自定义配置节的示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System.Configuration;
namespace My {
public class MyConfigSection : ConfigurationSection {
    [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
    public MyConfigInstanceCollection Instances {
        get { return (MyConfigInstanceCollection)this[""]; }
        set { this[""] = value; }
    }
}
public class MyConfigInstanceCollection : ConfigurationElementCollection {
    protected override ConfigurationElement CreateNewElement() {
        return new MyConfigInstanceElement();
    }

    protected override object GetElementKey(ConfigurationElement element) {
        //set to whatever Element Property you want to use for a key
        return ((MyConfigInstanceElement)element).Name;
    }
}

public class MyConfigInstanceElement : ConfigurationElement {
    //Make sure to set IsKey=true for property exposed as the GetElementKey above
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name {
        get { return (string) base["name"]; }
        set { base["name"] = value; }
    }

    [ConfigurationProperty("code", IsRequired = true)]
    public string Code {
        get { return (string) base["code"]; }
        set { base["code"] = value; }
    } } }

下面是一个如何从代码访问配置信息的示例。

1
2
3
4
5
6
7
var config = ConfigurationManager.GetSection("registerCompanies")
                 as MyConfigSection;

Console.WriteLine(config["Tata Motors"].Code);
foreach (var e in config.Instances) {
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}


不需要自定义配置节。

App.CONFIG

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="YourAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </configSections>
    <!-- value attribute is optional. omit if you just want a list of 'keys' -->
    <YourAppSettings>
       
       
       
       
       
    </YourAppSettings>
</configuration>

检索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// This casts to a NameValueCollection because the section is defined as a
/// AppSettingsSection in the configSections.
NameValueCollection settingCollection =
    (NameValueCollection)ConfigurationManager.GetSection("YourAppSettings");

var items = settingCollection.Count;
Debug.Assert(items == 4); // no duplicates... the last one wins.
Debug.Assert(settingCollection["duplicate"] =="bb");

// Just keys as per original question? done... use em.
string[] allKeys = settingCollection.AllKeys;

// maybe you did want key/value pairs. This is flexible to accommodate both.
foreach (string key in allKeys)
{
    Console.WriteLine(key +" :" + settingCollection[key]);
}


基于Jay Walker上面的答案,这是一个完整的工作示例,它增加了索引的能力:

1
2
3
4
5
6
7
8
9
10
<configuration>
    <configSections>
        <section name="registerCompanies"
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
       
       
    </registerCompanies>
</configuration>

下面是实现具有折叠集合的自定义配置节的示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System.Configuration;
using System.Linq;
namespace My
{
   public class MyConfigSection : ConfigurationSection
   {
      [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
      public MyConfigInstanceCollection Instances
      {
         get { return (MyConfigInstanceCollection)this[""]; }
         set { this[""] = value; }
      }
   }
   public class MyConfigInstanceCollection : ConfigurationElementCollection
   {
      protected override ConfigurationElement CreateNewElement()
      {
         return new MyConfigInstanceElement();
      }

      protected override object GetElementKey(ConfigurationElement element)
      {
         //set to whatever Element Property you want to use for a key
         return ((MyConfigInstanceElement)element).Name;
      }

      public new MyConfigInstanceElement this[string elementName]
      {
         get
         {
            return this.OfType<MyConfigInstanceElement>().FirstOrDefault(item => item.Name == elementName);
         }
      }
   }

   public class MyConfigInstanceElement : ConfigurationElement
   {
      //Make sure to set IsKey=true for property exposed as the GetElementKey above
      [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
      public string Name
      {
         get { return (string)base["name"]; }
         set { base["name"] = value; }
      }

      [ConfigurationProperty("code", IsRequired = true)]
      public string Code
      {
         get { return (string)base["code"]; }
         set { base["code"] = value; }
      }
   }
}

下面是一个如何从代码访问配置信息的示例。

1
2
3
4
5
6
7
8
MyConfigSection config =
   ConfigurationManager.GetSection("registerCompanies") as MyConfigSection;

Console.WriteLine(config.Instances["Honda Motors"].Code);
foreach (MyConfigInstanceElement e in config.Instances)
{
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}


根据JayWalker的回答,需要通过迭代"实例"集合来访问元素。IE.

1
2
3
4
5
6
var config = ConfigurationManager.GetSection("registerCompanies")
                 as MyConfigSection;

foreach (MyConfigInstanceElement e in config.Instances) {
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}

配置中的.assembly给出了异常,因为我将项目命名为"my"而不是"my.assembly"。如果使用此示例,请小心!