App.config:自定义配置嵌套部分

Vad*_* K. 4 c# configuration app-config sections

我找到了自定义配置处理程序的一个很好的例子,并尝试将它用于我自己的实现.

我已经像这样设置了App.config:

<configSections>
  <section name="DocumentationSettings" type="ConfigHandler.DocumentationSettings,Settings"/>
</configSections>

<DocumentationSettings>
  <DocumentationSections>
    <DocumentationSection Id="AAA">
      <SectionDescription Value="SectionDescriptionAAA"/>
    </DocumentationSection>
    <DocumentationSection Id="BBB">
      <SectionDescription Value="SectionDescriptionBBB"/>
    </DocumentationSection>
    <DocumentationSection Id="CCC">
      <SectionDescription Value="SectionDescriptionCCC"/>
    </DocumentationSection>
  </DocumentationSections>
</DocumentationSettings>
Run Code Online (Sandbox Code Playgroud)

我使用此代码访问我的自定义配置:

DocumentationSettings documentationSettings = ConfigurationManager.GetSection("DocumentationSettings") as DocumentationSettings;

foreach (DocumentationSectionConfigElement section in (documentationSettings.DocumentationSections.Sections))
{
    Console.WriteLine(section.Id);
    Console.WriteLine(section.SectionDescription.Properties.Value);
}
Run Code Online (Sandbox Code Playgroud)

首先'Console.WriteLine'完美无缺.

所以我有以下问题和实施相关的问题:

  1. 第二个'Console.WriteLine'出错,错误:无法识别的属性'Value'.我已经放了"public SectionDescription SectionDescription",因为"DocumentationSectionConfigElement"类暴露了属性访问,但我可能错了,我先尝试将它放入"DocumentationSectionCollection",但我不知道如何在那里实现它,对我来说似乎是"DocumentationSectionCollection"仅实现"集合"逻辑.

  2. 我想要像这样访问"字段":

    section.Id section.SectionDescription.Value

或者像这样:

section.Properties.Id
section.SectionDescription.Properties.Value
Run Code Online (Sandbox Code Playgroud)

我看到"Collection"允许使用这样的索引器方法直接使用这些属性:

public DocumentationSectionConfigElement this[int index]
Run Code Online (Sandbox Code Playgroud)

但我不能在"SectionDescription"类上实现索引器方法,因为它是一个单独的部分而不是集合,所以当我访问字段时,这个"属性"名称仍然存在.

  1. 为了能够在这些配置对象上使用LINQ,我需要添加什么?我的意思是这样的:

    (documentationSettings.DocumentationSections.Sections).Select(x => x.Id)

  2. 复杂的XML结构配置处理程序是否有很好的例子?从我发现的那些大多数简单的结构,如:

但没有像这样的复杂结构的任何例子:

<section>
  <subSections>
    <subSection name="111">
      <Description Value="AAA"></Description>
      <Headers>
        <Header type="Main">
         <Properties>
           <Property name="Property1"/>
           <Property name="Property2"/>
           <Property name="Property3"/>
         </Properties>
        </Header>
      </Headers>
    </subSection>
  </subSections>
</section>
Run Code Online (Sandbox Code Playgroud)

当您需要更好地组织应用程序配置时,它更接近真实场景.

  1. 如果"自定义配置处理程序"有效,"configSections"中的"sectionGroup"标记有什么意义,只要注册了一个"部分"就足够了?

  2. 为什么这些东西如此复杂?我花了这么多时间来处理这些"定制配置"的东西,我相信这些东西不应该那么复杂.是不是有任何Visual Studio加载项可以处理这些东西并根据XML配置结构生成代码?

这是我的配置处理程序实现:

public class DocumentationSettings : ConfigurationSection
{
    [ConfigurationProperty("DocumentationSections")]
    public DocumentationSections DocumentationSections
    {
        get { return (DocumentationSections)base["DocumentationSections"]; }
    }
}

public class DocumentationSections : ConfigurationElement
{
    [ConfigurationProperty("", IsDefaultCollection = true)]
    public DocumentationSectionCollection Sections
    {
        get { return (DocumentationSectionCollection)base[""]; }
    }
}

public class SectionDescription : ConfigurationElement
{
    [ConfigurationProperty("SectionDescription")]
    public new SectionDescriptionConfigElement Properties
    {
        get { return (SectionDescriptionConfigElement)base["SectionDescription"]; }
    }
}

public class DocumentationSectionCollection : ConfigurationElementCollection
{
    public DocumentationSectionCollection()
    {
        DocumentationSectionConfigElement details = (DocumentationSectionConfigElement)CreateNewElement();
        if (details.Id != "")
        {
            Add(details);
        }
    }

    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.BasicMap; }
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new DocumentationSectionConfigElement();
    }

    protected override Object GetElementKey(ConfigurationElement element)
    {
        return ((DocumentationSectionConfigElement)element).Id;
    }

    public DocumentationSectionConfigElement this[int index]
    {
        get { return (DocumentationSectionConfigElement)BaseGet(index); }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }

    new public DocumentationSectionConfigElement this[string name]
    {
        get { return (DocumentationSectionConfigElement)BaseGet(name); }
    }

    public int IndexOf(DocumentationSectionConfigElement details)
    {
        return BaseIndexOf(details);
    }

    public void Add(DocumentationSectionConfigElement details)
    {
        BaseAdd(details);
    }
    protected override void BaseAdd(ConfigurationElement element)
    {
        BaseAdd(element, false);
    }

    public void Remove(DocumentationSectionConfigElement details)
    {
        if (BaseIndexOf(details) >= 0)
            BaseRemove(details.Id);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }

    public void Remove(string name)
    {
        BaseRemove(name);
    }

    public void Clear()
    {
        BaseClear();
    }

    protected override string ElementName
    {
        get { return "DocumentationSection"; }
    }
}

public class DocumentationSectionConfigElement : ConfigurationElement
{
    [ConfigurationProperty("Id", IsRequired = true, IsKey = true)]
    [StringValidator(InvalidCharacters = "  ~!@#$%^&*()[]{}/;’\"|\\")]
    public string Id
    {
        get { return (string)this["Id"]; }
        set { this["Id"] = value; }
    }

    [ConfigurationProperty("Name", IsRequired = false)]
    public string Name
    {
        get { return (string)this["Name"]; }
        set { this["Name"] = value; }
    }

    [ConfigurationProperty("SectionDescription")]
    public SectionDescription SectionDescription
    {
        get { return ((SectionDescription)base["SectionDescription"]); }
    }
}

public class SectionDescriptionConfigElement : ConfigurationElement
{
    [ConfigurationProperty("Value", IsRequired = true)]
    public string Value
    {
        get { return (string)this["Value"]; }
        set { this["Value"] = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

Vad*_* K. 6

由于此处没有活动,我将尝试逐一回答我的问题:

  1. 发现这篇很好的文章描述了很多东西,并展示了一些自定义配置实现的复杂示例.

  2. 我找到了这个伟大的工具 - ".NET配置代码生成器",它完全符合我的要求 - 它采用XML结构并生成自定义配置代码.