带有简单“添加”元素列表的自定义app.config部分


88

如何创建仅是简单add元素列表的自定义app.config部分?

我发现了一些示例示例(例如,如何在app.config中创建自定义配置部分?),如下所示:

<RegisterCompanies>
  <Companies>
    <Company name="Tata Motors" code="Tata"/>
    <Company name="Honda Motors" code="Honda"/>
  </Companies>
</RegisterCompanies>

但是,如何避免多余的收集元素(“公司”),使其看起来与appSettingsconnectionStrings部分相同?换句话说,我想要:

<registerCompanies>
  <add name="Tata Motors" code="Tata"/>
  <add name="Honda Motors" code="Honda"/>
</registerCompanies>

Answers:


115

带有基于OP配置文件的代码的完整示例:

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

这是示例示例,用于实现折叠集合的自定义配置部分

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; }
    } } }

这是如何从代码访问配置信息的示例。

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); 
}

@Jay Walker您如何才能访问所需的项目,即:-config.Instances [“ Tata Motors”]是否可以这样做?
西蒙(Simon)

2
应该指出标记<configSection>应在其正确的位置<configuration>才能正常工作!
Vedran Kopanja 2014年

2
还应该指出,<add是必需的。创建您自己的自定义<标签不适用于此答案
Steve是D的

8
AFAIK-此代码“ config [“ Tata Motors”]“将不会编译b / c配置的索引器在内部受保护。您将必须找到一种方法来自己枚举集合中的项目。
CedricB

1
@JayWalker都很好。您的示例中该节类型的“ My.MyConfiguration,My.Assembly”让我感到震惊。我只需要使用“ MyAssembly.MyConfiguration,MyAssembly”进行尝试。
格伦

38

无需自定义配置部分。

应用配置

<?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>
        <add key="one" value="1" />
        <add key="two" value="2"/>
        <add key="three" value="3"/>
        <add key="duplicate" value="aa"/>
        <add key="duplicate" value="bb"/>
    </YourAppSettings>
</configuration>

取回

// 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]);
}

1
我想它不能严格回答OP的问题,但是我认为这是一个有效的解决方案,并且简单得多。至少它对我有帮助!
styl0r

2
@ styl0r你是对的。它没有严格回答。如果必须使用属性名称/代码而不是我的解决方案键/值,则必须使用真正的自定义部分。但是,我认为您可以控制配置文件,并且比做自定义类要好得多。
JJS

4
非常简单干净!无需任何其他自定义部分/元素膨胀软件。
的Ondrej

2
如果您愿意,也可以仅通过更改版本号将其更新为Version = 4.0.0.0。如果您只需要其他简单列表,这是imo的最佳答案。对于“ System.Configuration.ConnectionStringsSection”也可以执行相同的操作,尽管重复项的处理与应用程序设置略有不同。
沙皮罗

@Sharpiro您的程序集版本有问题吗?我认为,即使对于较新版本的框架,程序集绑定也将是最先进的。
JJS

22

根据上面的杰伊·沃克的回答,这是一个完整的工作示例,增加了执行索引的功能:

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

这是示例示例,用于实现折叠集合的自定义配置部分

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; }
      }
   }
}

这是如何从代码访问配置信息的示例。

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);
}

2
这很棒。现在,我们只需要示例代码来更新,添加和删除实例。
斯科特·哈金森

1
感谢您的解决方案!谁在MS上做到这一点……这的确是不必要的复杂。
Switch386 '19

8

根据杰伊·沃克(Jay Walker)的回答,访问元素需要通过遍历“实例”集合来完成。即。

var config = ConfigurationManager.GetSection("registerCompanies") 
                 as MyConfigSection;

foreach (MyConfigInstanceElement e in config.Instances) { 
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.