我找到了一个关于自定义配置处理程序的很好的例子并尝试用它来实现我的代码。
我已经像这样设置了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>
我使用这段代码来访问我的自定义配置:
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'。我已经将 "public SectionDescription SectionDescription" 放入了 "DocumentationSectionConfigElement" 类中暴露的属性访问器,但我可能是错的。我先尝试将其放入 "DocumentationSectionCollection" 中,但我不知道如何在那里实现它,对我来说,似乎 "DocumentationSectionCollection" 只实现了 "Collection" 逻辑。
我想访问 "fields",可以像这样同时访问:
section.Id section.SectionDescription.Value
或者像这样:
section.Properties.Id
section.SectionDescription.Properties.Value
我看到“Collection”允许使用索引器方法直接使用这些属性,例如:
public DocumentationSectionConfigElement this[int index]
但是我无法在"SectionDescription"类上实现索引器方法,因为它只是一个单独的部分而不是集合,所以当我访问字段时,这个"Properties"名称仍然存在。
我需要添加什么才能在这些配置对象上使用LINQ? 我的意思是这样的:
(documentationSettings.DocumentationSections.Sections).Select(x => x.Id)
有没有真正好的例子可以展示复杂的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>
当你需要更好地组织应用程序配置时,“sectionGroup”标签比较贴近实际情况。
如果“自定义配置处理程序”能够工作并且已经注册了一个“section”,那么“configSections”中的“sectionGroup”标签有什么意义呢?
为什么所有这些东西都如此复杂?我已经在这些“自定义配置”事务上花了很多时间,我认为不应该这样复杂。难道没有任何可以处理这些事物并基于XML配置结构生成代码的Visual Studio插件吗?
这是我的配置处理程序实现:
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; }
}
}