app.config (C#) 中的嵌套自定义元素

Posted

技术标签:

【中文标题】app.config (C#) 中的嵌套自定义元素【英文标题】:Nested custom elements in app.config (C#) 【发布时间】:2011-07-31 08:36:36 【问题描述】:

祝大家,

几个小时以来,我一直试图弄清楚如何从 app.config 文件中读取设置:

<?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="Databases" type="McFix.DatabaseSection, McFix"/>
  </configSections>

  <Databases>
    <Database name="database">
      <Tables>
        <Table name="be_sessions">
          <Columns>
            <Column name="sess_id">
            </Column>
          </Columns>
        </Table>
      </Tables>
    </Database>
  </Databases>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

自定义处理程序类的代码是here,也复制如下:

public class DatabaseSection : ConfigurationSection

    [ConfigurationProperty("Databases", IsDefaultCollection = false)]
    public DatabaseInstanceCollection Databases
    
        get  return (DatabaseInstanceCollection)this["Databases"]; 
        set  this[""] = value; 
    

[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap )]
public class DatabaseInstanceCollection : ConfigurationElementCollection

    protected override ConfigurationElement CreateNewElement()
    
        return new DatabaseElement();
    
    protected override object GetElementKey(ConfigurationElement element)
    
        return ((DatabaseElement)element).Name;
    

public class DatabaseElement : ConfigurationElement

    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    
        get  return (string)base["name"]; 
        set  base["name"] = value; 
    


public class TableSection : ConfigurationSection

    [ConfigurationProperty("Tables", IsDefaultCollection = true)]
    public TableInstanceCollection Tables
    
        get  return (TableInstanceCollection)this["Tables"]; 
        set  this[""] = value; 
    


[ConfigurationCollection(typeof(TableElement), AddItemName = "Table", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class TableInstanceCollection : ConfigurationElementCollection

    protected override ConfigurationElement CreateNewElement()
    
        return new TableElement();
    
    protected override object GetElementKey(ConfigurationElement element)
    
        return ((TableElement)element).Name;
    


public class TableElement : ConfigurationElement

    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    
        get  return (string)base["name"]; 
        set  base["name"] = value; 
    


public class ColumnSection : ConfigurationSection

    [ConfigurationProperty("Columns", IsDefaultCollection = true)]
    public ColumnInstanceCollection Columns
    
        get  return (ColumnInstanceCollection)this["Columns"]; 
        set  this[""] = value; 
    


[ConfigurationCollection(typeof(ColumnElement), AddItemName = "Column", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class ColumnInstanceCollection : ConfigurationElementCollection

    protected override ConfigurationElement CreateNewElement()
    
        return new ColumnElement();
    
    protected override object GetElementKey(ConfigurationElement element)
    
        return ((ColumnElement)element).Name;
    


public class ColumnElement : ConfigurationElement

    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    
        get  return (string)base["name"]; 
        set  base["name"] = value; 
    

问题是当我尝试通过 GetSection 方法获取“数据库”部分时:

Configuration Config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
DatabaseSection DbConfig = Config.GetSection("Databases") as DatabaseSection;

程序抛出一个 ConfigurationErrorsException,报告​​“无法识别的元素'数据库'”,尽管它在通过 DatabaseSection 的 get 方法之后这样做,即使我将 DatabaseInstanceCollection 的 AddItemName 定义为“数据库”。我是否遗漏了一些能让底层代码正确读取 app.config 的属性?

【问题讨论】:

SO 格式有什么问题?此外,您需要为此做更多的工作。描述什么对你不起作用以及你的问题是什么。没有人会通读您的代码以找出问题所在。举出你失败的例子。 您是否在询问如何使用您定义的类读取配置设置?我在您的代码中没有看到您实际阅读的任何内容。 如果您想发布 code、XMLdata 示例,请在文本编辑器中突出显示这些行并单击“code samples”按钮( )在编辑器工具栏上很好地格式化和语法高亮它!如果您这样做,那么格式化并很好地显示它! 我向大家道歉,有一段时间没有在论坛上发布问题(主要是因为我正在回答其他人的问题),我失去了联系。 【参考方案1】:

必填链接:

Unraveling the Mysteries of .NET 2.0 Configuration Decoding the Mysteries of .NET 2.0 Configuration Cracking the Mysteries of .NET 2.0 Configuration

粗略一看,您的问题似乎出在这一行:

[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap )]

这表示 .config 文件应如下所示:

<Databases>
    <add><!-- Database goes here --></add>
</Databases>

即您的 Databases 元素需要一个“添加”子元素,以指示要将项目添加到集合中。

您应该尝试将AddItemName 属性从“add”更改为“Database”:

[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "Database", CollectionType = ConfigurationElementCollectionType.BasicMap )]

(我没有机会测试这个,可能还有其他问题)

【讨论】:

感谢 Kragen,我在这里浏览了 .NET 的类似应用程序配置的问答,并访问了您之前提到的链接,但唉。我试图将 AddItemName 更改为“数据库”,但也无济于事。我怀疑必须为“数据库”部分声明“数据库”元素,尽管我认为这是通过 ConfigurationCollection 属性的“AddItemName”属性完成的。 @user696034 它对错误消息有影响吗?我还发现DatabaseElement 配置元素没有引用TableSection 配置部分,因此我预计即使在解决上述问题后也可能会导致失败。 我已经设法让整个事情顺利进行,但你是对的 Kragen,有必要将 TableInstanceCollection 添加到 DatabaseElement 并将 ColumnInstanceCollection 添加到 TableElement。此外,DatabaseSection 必须像这样才能工作:【参考方案2】:

你说得对,Kragen,我必须删除 Table/ColumnSection 并将 Table/ColumnInstanceCollection 添加到 Database/TableElement。 DatabaseSection' Databases 属性必须是这样的:

[ConfigurationProperty("", IsDefaultCollection = true)]
        public DatabaseInstanceCollection Databases
        
            get  return (DatabaseInstanceCollection)this[""]; 
        

【讨论】:

以上是关于app.config (C#) 中的嵌套自定义元素的主要内容,如果未能解决你的问题,请参考以下文章

c#自定义app.config生成配置系统初始化失败异常

C# app.config 遍历读取自定义节点

C# 如何添加自定义键盘处理事件 如何配置app.config ? | csharp key press event tutorial and app.config

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

使用映射库将嵌套对象映射到 C# 中的自定义对象

C# 控制台应用程序计时器问题