如何使用 ConfigurationElementCollection 实现 ConfigurationSection
我正在尝试在项目中实现自定义配置部分,但我不断遇到我不理解的异常。我希望有人能填补这里的空白。
我的 App.config
看起来像这样:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ServicesSection" type="RT.Core.Config.ServicesConfigurationSectionHandler, RT.Core"/>
</configSections>
<ServicesSection type="RT.Core.Config.ServicesSection, RT.Core">
<Services>
<AddService Port="6996" ReportType="File" />
<AddService Port="7001" ReportType="Other" />
</Services>
</ServicesSection>
</configuration>
我有一个 ServiceConfig
元素定义如下:
public class ServiceConfig : ConfigurationElement
{
public ServiceConfig() {}
public ServiceConfig(int port, string reportType)
{
Port = port;
ReportType = reportType;
}
[ConfigurationProperty("Port", DefaultValue = 0, IsRequired = true, IsKey = true)]
public int Port
{
get { return (int) this["Port"]; }
set { this["Port"] = value; }
}
[ConfigurationProperty("ReportType", DefaultValue = "File", IsRequired = true, IsKey = false)]
public string ReportType
{
get { return (string) this["ReportType"]; }
set { this["ReportType"] = value; }
}
}
我有一个 ServiceCollection
定义如下
public class ServiceCollection : ConfigurationElementCollection
{
public ServiceCollection()
{
Console.WriteLine("ServiceCollection Constructor");
}
public ServiceConfig this[int index]
{
get { return (ServiceConfig)BaseGet(index); }
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
public void Add(ServiceConfig serviceConfig)
{
BaseAdd(serviceConfig);
}
public void Clear()
{
BaseClear();
}
protected override ConfigurationElement CreateNewElement()
{
return new ServiceConfig();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ServiceConfig) element).Port;
}
public void Remove(ServiceConfig serviceConfig)
{
BaseRemove(serviceConfig.Port);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(string name)
{
BaseRemove(name);
}
}
:我缺少的部分是为处理程序做什么。最初,我尝试实现一个 IConfigurationSectionHandler
但发现两件事:
- 它不起作用,
- 它已被弃用。
我现在完全不知道该怎么做才能从配置中读取数据。请帮忙!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
前面的答案是正确的,但我也会给你所有的代码。
您的 app.config 应如下所示:
您的
ServiceConfig
和ServiceCollection
类保持不变。你需要一个新的类:
这应该可以解决问题。要使用它,您可以使用:
The previous answer is correct but I'll give you all the code as well.
Your app.config should look like this:
Your
ServiceConfig
andServiceCollection
classes remain unchanged.You need a new class:
And that should do the trick. To consume it you can use:
如果您正在寻找如下所示的自定义配置部分
,那么您可以使用我的配置部分实现,以便开始将
System.Configuration
程序集引用添加到您的项目中,首先查看我使用的每个嵌套元素一个是具有两个属性的凭据,因此让我们首先添加它
Credentials 元素
PrimaryAgent 和 secondaryAgent
两者具有相同的属性,看起来像是一组服务器的地址,用于主服务器和辅助服务器故障转移,因此您只需要为这两个元素创建一个元素类,如下所示,
我将在本文后面解释如何将两个不同的元素与一个类一起使用,让我们跳过 SiteId,因为它没有区别。您只需创建一个与上面相同的类,仅具有一个属性。让我们看看如何实现 Lanes 集合,
它分为两部分,首先您必须创建一个元素实现类,然后您必须创建集合元素类
LaneConfigElement
您可以注意到
LanElement 的一个属性
是一个枚举,如果您尝试在配置中使用枚举中未定义的任何其他值,应用程序将在启动时抛出System.Configuration.ConfigurationErrorsException
。好的,让我们继续进行集合定义,您可以注意到我已经设置了
AddItemName = "Lane"
您可以为集合条目项目选择您喜欢的任何内容,我更喜欢使用“添加”默认项,但是我只是为了这篇文章而改变它。现在我们所有的嵌套元素都已经实现了,我们应该将所有这些元素聚合在一个必须实现 System.Configuration.ConfigurationSection
CustomApplicationConfigSection 的
类中。现在您可以看到我们已经名为
PrimaryAgent
和SecondaryAgent
的两个属性都具有相同的类型,现在您可以轻松理解为什么我们针对这两个元素只有一个实现类。在您可以在 app.config (或 web.config)中使用这个新发明的配置部分之前,您只需告诉您的应用程序您已经发明了自己的配置部分并给予它一些尊重,为此您必须添加以下行在 app.config 中(可能就在根标记开始之后)。
注意: MyAssemblyName 应该不带 .dll,例如,如果您的程序集文件名为 myDll.dll,则使用 myDll 而不是 myDll.dll
来检索此配置,在您的应用程序中的任何位置使用以下代码行(
我希望在上面)这篇文章将帮助您开始使用有点复杂的自定义配置部分。
快乐编码:)
****编辑****
要在
LaneConfigCollection
上启用 LINQ,您必须实现IEnumerable
添加以下
GetEnumerator
实现并为那些仍然对如何收益感到困惑的人 确实有效,请阅读这篇好文章
两个上述文章的要点是
If you are looking for a custom configuration section like following
then you can use my implementation of configuration section so to get started add
System.Configuration
assembly reference to your projectLook at the each nested elements I used, First one is Credentials with two attributes so lets add it first
Credentials Element
PrimaryAgent and SecondaryAgent
Both has the same attributes and seem like a Address to a set of servers for a primary and a failover, so you just need to create one element class for both of those like following
I'll explain how to use two different element with one class later in this post, let us skip the SiteId as there is no difference in it. You just have to create one class same as above with one property only. let us see how to implement Lanes collection
it is splitted in two parts first you have to create an element implementation class then you have to create collection element class
LaneConfigElement
you can notice that one attribute of
LanElement
is an Enumeration and if you try to use any other value in configuration which is not defined in Enumeration application will throw anSystem.Configuration.ConfigurationErrorsException
on startup. Ok lets move on to Collection Definitionyou can notice that I have set the
AddItemName = "Lane"
you can choose whatever you like for your collection entry item, i prefer to use "add" the default one but i changed it just for the sake of this post.Now all of our nested Elements have been implemented now we should aggregate all of those in a class which has to implement
System.Configuration.ConfigurationSection
CustomApplicationConfigSection
Now you can see that we have two properties with name
PrimaryAgent
andSecondaryAgent
both have the same type now you can easily understand why we had only one implementation class against these two element.Before you can use this newly invented configuration section in your app.config (or web.config) you just need to tell you application that you have invented your own configuration section and give it some respect, to do so you have to add following lines in app.config (may be right after start of root tag).
NOTE: MyAssemblyName should be without .dll e.g. if you assembly file name is myDll.dll then use myDll instead of myDll.dll
to retrieve this configuration use following line of code any where in your application
I hope above post would help you to get started with a bit complicated kind of custom config sections.
Happy Coding :)
****Edit****
To Enable LINQ on
LaneConfigCollection
you have to implementIEnumerable<LaneConfigElement>
And Add following implementation of
GetEnumerator
for the people who are still confused about how yield really works read this nice article
Two key points taken from above article are
这是配置收集的通用代码:
在拥有
GenericConfigurationElementCollection
后,您可以在配置部分简单地使用它(这是我的调度程序的示例):
配置元素是 config 这里:
配置文件将如下所示:
希望它有所帮助!
This is generic code for configuration collection :
After you have
GenericConfigurationElementCollection
,you can simple use it in the config section (this is an example from my Dispatcher):
The Config Element is config Here:
The config file would look like this:
Hope it help !
对于那些不想手动编写所有配置样板的人来说,这是一个更简单的选择...
1) 安装 来自 NuGet 的 Nerdle.AutoConfig
2) 定义您的 ServiceConfig 类型(具体类或只是一个接口,两者都可以)
3) 您需要一个类型来保存集合,例如
4) 添加配置部分,例如so(注意驼峰式命名)
5)使用 AutoConfig 进行映射
An easier alternative for those who would prefer not to write all that configuration boilerplate manually...
1) Install Nerdle.AutoConfig from NuGet
2) Define your ServiceConfig type (either a concrete class or just an interface, either will do)
3) You'll need a type to hold the collection, e.g.
4) Add the config section like so (note camelCase naming)
5) Map with AutoConfig
尝试从 ConfigurationSection 继承。此博文菲尔·哈克(Phil Haack)有一个例子。
已确认,根据 IConfigurationSectionHandler 的文档:
Try inheriting from ConfigurationSection. This blog post by Phil Haack has an example.
Confirmed, per the documentation for IConfigurationSectionHandler: