2011-04-07 330 views
5

G'da给大家,嵌套自定义元素

几个小时我一直在试图找出如何从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方法去,即使我定义为AddItemName作为DatabaseInstanceCollection“数据库”之后。我是否错过了一些可以让底层代码正确读取app.config的属性?

+2

SO格式化有什么问题?此外,你需要为此做更多的工作。描述什么不适合你,以及你的问题是什么。没有人会通读你的代码来弄清楚哪里出了问题。举例说明你的失败。 – 2011-04-07 04:41:16

+1

您是否问过如何使用您定义的类在配置设置中读取?我没有在你的代码中看到任何你真正阅读过的东西。 – 2011-04-07 04:43:02

+0

如果你想发布**代码,XML **或** data **样本,在文本编辑器中突出显示这些行,然后单击“代码(编辑器)工具栏上的“样本”按钮(“{}”),以精确地格式化和语法突出显示它!如果你愿意,SO **会**格式化并显示出来! – 2011-04-07 04:52:11

回答

7

强制性链接:

匆匆一瞥,好像你的问题后,在这条线:

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

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

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

I.e.您的Databases元素期望有一个“添加”子元素,表示要将某个项目添加到该集合中。

你应该尝试从“添加”到“数据库”改变AddItemName属性:

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

(我没有机会来测试这一点,有可能是其他问题)

+0

谢谢Kragen,我浏览了类似的应用程序配置的Q&A。NET在这里,并访问过你之前提到的链接,但唉。我试图将AddItemName更改为“数据库”,但无济于事。 我有一个怀疑,“数据库”元素必须声明的部分“数据库”,虽然我会认为它通过ConfigurationCollection属性的“AddItemName”属性完成。 – 2011-04-08 00:24:45

+1

@ user696034它对错误消息有影响吗?我也发现'DatabaseElement'配置元素没有引用'TableSection'配置部分,所以我认为即使解决了上述问题,也可能会导致失败。 – Justin 2011-04-08 00:53:10

+1

我已经设法让整个事情发展,但你是正确的Kragen,有必要将TableInstanceCollection添加到DatabaseElement和ColumnInstanceCollection TableElement。 另外,DatabaseSection必须像这样工作: – 2011-04-08 01:16:45

1

你'正确,Kragen,我必须删除Table/ColumnSection并将Table/ColumnInstanceCollection添加到Database/TableElement。 DatabaseSection'数据库属性必须是这样的:

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