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

Posted

技术标签:

【中文标题】带有“添加”元素的简单列表的自定义 app.config 部分【英文标题】:Custom app.config section with a simple list of "add" elements 【发布时间】:2011-02-12 16:04:52 【问题描述】:

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

我找到了一些自定义部分的示例(例如How to create custom config section in 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>

【问题讨论】:

另见***.com/questions/1779117/… 【参考方案1】:

基于 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"] 是否可以这样做? 应该指出&lt;configSection&gt; 应该在&lt;configuration&gt; 标签之后才能工作! 还应该指出 AFAIK - 此代码“config[“Tata Motors”]”不会编译 b/c,配置的索引器受内部保护。您必须找到一种方法来自行枚举集合中的项目。 @JayWalker 一切都好。您的示例中的“My.MyConfiguration,My.Assembly”对于节类型抛出了我。我只需要使用“MyAssembly.MyConfiguration,MyAssembly”来完成我的尝试。【参考方案2】:

无需自定义配置部分。

app.config

<?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>

检索值

// AppSettingsSection can be cast to a NameValueCollection
NameValueCollection settingCollection = 
(NameValueCollection)ConfigurationManager.GetSection("YourAppSettings");

// An array of the keys. No Duplicates
//  "one", "two", "three", "duplicate" 
string[] allKeys = settingCollection.AllKeys; 
    
// key/value pairs
// one : 1
// two : 2
// three : 3
// duplicate : bb 
foreach (string key in allKeys)

   Console.WriteLine(key + " : " + settingCollection[key]);


// Duplicates behavior
var items = settingCollection.Count;
Debug.Assert(items == 4); // no duplicates. Last element wins.
Debug.Assert(settingCollection["duplicate"] == "bb");

【讨论】:

我想它并没有严格回答 OP 的问题,但我认为这是一个有效的解决方案,而且更简单。至少它帮助了我! @styl0r 你是对的。它没有严格回答它。如果您必须使用属性名称/代码而不是我的解决方案键/值,则必须使用真正的自定义部分。但是,我假设您可以控制配置文件,并且有比创建自定义类更好的事情要做。 非常简单干净!无需任何额外的自定义部分/元素膨胀软件。 如果您愿意,也可以通过更改版本号来更新到 Version=4.0.0.0。如果您只需要额外的简单列表,这是 imo 的最佳答案。 “System.Configuration.ConnectionStringsSection”也可以这样做,尽管重复的处理方式与应用设置略有不同。 @Sharpiro 您对程序集版本有疑问吗?我认为程序集绑定会同步进行,即使对于较新版本的框架也是如此。【参考方案3】:

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

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

【讨论】:

这很棒。现在我们只需要更新、添加和删除实例的示例代码。 感谢您的解决方案!谁在 MS 做了这个......这真的是不必要的复杂。【参考方案4】:

根据 Jay Walker 的回答,需要通过遍历“Instances”集合来访问元素。即。

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

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

【讨论】:

以上是关于带有“添加”元素的简单列表的自定义 app.config 部分的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 xamarin 的自定义对话框中添加列表视图

带有 XIB 的自定义 UITableViewCell

带有子元素的 Android 自定义可展开/可折叠视图

带有 :before 的自定义列表项目符号

带有 RecyclerView 的自定义 AlertDialog - 列表始终为空

如何获取已注册的自定义元素列表