关于c#:App.config:自定义配置嵌套部分

App.config: custom configuration nested sections

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

我设置了app.config,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

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

1
2
3
4
5
6
7
DocumentationSettings documentationSettings = ConfigurationManager.GetSection("DocumentationSettings") as DocumentationSettings;

foreach (DocumentationSectionConfigElement section in (documentationSettings.DocumentationSections.Sections))
{
    Console.WriteLine(section.Id);
    Console.WriteLine(section.SectionDescription.Properties.Value);
}

第一个"console.writeline"工作正常。

因此,我有以下问题和与实施相关的问题:

  • 第二个"console.writeline"出现错误,错误:无法识别的属性"value"。自从"documentationsectionconfigelement"类公开属性访问以来,我已经放置了"public sectiondescription sectiondescription",但我可能是错的,我尝试首先将它放入"documentationsectioncollection",但我不知道如何在那里实现它,对于我来说,"documentationsectioncollection"似乎只实现"collection"逻辑。C.

  • 我想访问"字段",或者两者都像这样:

    身份证章节描述值

  • 或者像这样:

    2

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

    1
    public DocumentationSectionConfigElement this[int index]

    但是我不能在"sectiondescription"类上实现indexer方法,因为它是单个节而不是集合,所以当我访问字段时,这个"properties"名称会一直存在。

  • 我需要添加什么才能在这些配置对象上使用LINQ?我的意思是这样:

    (documentationsettings.documentationsections.sections).选择(x=>x.id)

  • 复杂的XML结构配置处理程序有什么很好的例子吗?从我发现的那些结构中,主要有如下简单的结构:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <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>

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

  • 如果"自定义配置处理程序"工作并且注册了一个"节"就足够了,那么"configSections"中的"sectionGroup"标记的意义是什么?

  • 为什么这些东西这么复杂?我花了太多时间来做这些"定制配置"的事情,我相信这些事情不应该那么复杂。是否没有任何Visual Studio加载项可以处理这些内容并基于XML配置结构生成代码?

  • 以下是我的配置处理程序实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    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; }
        }
    }

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

  • 找到了这篇很好的文章,它描述了很多东西,并显示了一些自定义配置实现的复杂示例。

  • 我找到了一个很棒的工具——".NET配置代码生成器",它可以完全满足我的需要——它采用XML结构并生成自定义配置代码。