.NET4 中带有集合的简单自定义配置部分
我正在尝试为 .NET4 应用程序编写一个非常简单的自定义配置部分。我的目标是这样的:
<configuration>
<configSections>
<section name="myServices" type="My.ConfigSection, My.Assembly" />
</configSections>
<myServices>
<add name="First" />
<add name="Second" />
</myServices>
</configuration>
但是,当我调用 ConfigurationManager.GetSection("myServices")
时,我不断收到 ConfigurationErrorsException
: 'Unrecognized element 'add''。我已经盯着它看了有一段时间了,但还没有弄清楚我做错了什么。下面是我的代码。它包含三个类:ConfigSection
、MyServiceSettingsCollection
和 MyServiceSettings
。
首先是代表整个配置部分的类。它有一个 MyServiceSettingsCollection
类型的无名默认集合。 IsDefaultCollection
属性应该允许我直接“添加”到我的来自根元素的集合。
public sealed class ConfigSection : ConfigurationSection
{
private static readonly ConfigurationProperty _propMyServices;
private static readonly ConfigurationPropertyCollection _properties;
public static ConfigSection Instance { get { return _instance; } }
static ConfigSection()
{
_propMyServices = new ConfigurationProperty(
null, typeof(MyServiceSettingsCollection), null,
ConfigurationPropertyOptions.IsDefaultCollection);
_properties = new ConfigurationPropertyCollection { _propMyServices };
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public MyServiceSettingsCollection MyServices
{
get { return (MyServiceSettingsCollection) base[_propMyServices]; }
set { base[_propMyServices] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return _properties; } }
}
接下来是集合类本身。它的类型为 AddRemoveClearMap
。
[ConfigurationCollection(typeof(MyServiceSettings),
CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public sealed class MyServiceSettingsCollection : ConfigurationElementCollection
{
public MyServiceSettings this[int index]
{
get { return (MyServiceSettings) BaseGet(index); }
set
{
if (BaseGet(index) != null) { BaseRemoveAt(index); }
BaseAdd(index, value);
}
}
public new MyServiceSettings this[string key]
{
get { return (MyServiceSettings) BaseGet(key); }
}
protected override ConfigurationElement CreateNewElement()
{
return new MyServiceSettings();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MyServiceSettings) element).Key;
}
}
最后是集合中元素的类。目前,此类有一个属性,但稍后会有更多属性(这会阻止我使用 NameValueSectionHandler
)。
public class MyServiceSettings : ConfigurationElement
{
private static readonly ConfigurationProperty _propName;
private static readonly ConfigurationPropertyCollection properties;
static MyServiceSettings()
{
_propName = new ConfigurationProperty("name", typeof(string), null, null,
new StringValidator(1),
ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey);
properties = new ConfigurationPropertyCollection { _propName };
}
[ConfigurationProperty("name", DefaultValue = "",
Options = ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey)]
public string Name
{
get { return (string) base[_propKey]; }
set { base[_propKey] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return properties; } }
}
I'm trying to write a very simple custom configuration section for a .NET4 application. My goal is this:
<configuration>
<configSections>
<section name="myServices" type="My.ConfigSection, My.Assembly" />
</configSections>
<myServices>
<add name="First" />
<add name="Second" />
</myServices>
</configuration>
However, I keep getting a ConfigurationErrorsException
: 'Unrecognized element 'add'' when I call ConfigurationManager.GetSection("myServices")
. I've been staring at it for a while now but haven't figured out yet what I'm doing wrong. Below is my code. It's three classes: ConfigSection
, MyServiceSettingsCollection
and MyServiceSettings
.
First the class that represents the entire config section. It has a nameless default collection of type MyServiceSettingsCollection
. The IsDefaultCollection
property should allow me to 'add' directly to my collection from the root element.
public sealed class ConfigSection : ConfigurationSection
{
private static readonly ConfigurationProperty _propMyServices;
private static readonly ConfigurationPropertyCollection _properties;
public static ConfigSection Instance { get { return _instance; } }
static ConfigSection()
{
_propMyServices = new ConfigurationProperty(
null, typeof(MyServiceSettingsCollection), null,
ConfigurationPropertyOptions.IsDefaultCollection);
_properties = new ConfigurationPropertyCollection { _propMyServices };
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public MyServiceSettingsCollection MyServices
{
get { return (MyServiceSettingsCollection) base[_propMyServices]; }
set { base[_propMyServices] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return _properties; } }
}
Next, the collection class itself. It is of type AddRemoveClearMap
.
[ConfigurationCollection(typeof(MyServiceSettings),
CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public sealed class MyServiceSettingsCollection : ConfigurationElementCollection
{
public MyServiceSettings this[int index]
{
get { return (MyServiceSettings) BaseGet(index); }
set
{
if (BaseGet(index) != null) { BaseRemoveAt(index); }
BaseAdd(index, value);
}
}
public new MyServiceSettings this[string key]
{
get { return (MyServiceSettings) BaseGet(key); }
}
protected override ConfigurationElement CreateNewElement()
{
return new MyServiceSettings();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MyServiceSettings) element).Key;
}
}
And finally a class for the elements in the collection. For now, this class has one property but there will be more later (which prevents me from using NameValueSectionHandler
).
public class MyServiceSettings : ConfigurationElement
{
private static readonly ConfigurationProperty _propName;
private static readonly ConfigurationPropertyCollection properties;
static MyServiceSettings()
{
_propName = new ConfigurationProperty("name", typeof(string), null, null,
new StringValidator(1),
ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey);
properties = new ConfigurationPropertyCollection { _propName };
}
[ConfigurationProperty("name", DefaultValue = "",
Options = ConfigurationPropertyOptions.IsRequired |
ConfigurationPropertyOptions.IsKey)]
public string Name
{
get { return (string) base[_propKey]; }
set { base[_propKey] = value; }
}
protected override ConfigurationPropertyCollection Properties
{ get { return properties; } }
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我发现了看似随机的修复。而不是这样:
您应该使用:
不知道两者之间有什么区别。对我来说,它们看起来惊人地相似……或者至少,没有任何地方表明为什么其中一个比另一个更受欢迎。
Ok, I found the seemingly random fix. Instead of this:
you should use:
No idea what the difference is between the two. To me, they look strikingly similar... or at least, there is no suggestion anywhere why one is preferred over the other.
由于我在这方面花了很多时间,所以我想添加一个我刚刚在这次提交中实现的真实示例: https://github.com/rhythmagency/formulate/commit/4d2a95e1a82eb6b3500ab0869b8f8b15bd3deaa9
这是我的 web.config 目标(我能够实现):
这是最高级别的课程-level“模板”配置部分:
这是下一个级别,集合类:
这是最深级别的类(各个模板):
对我来说重要的是在
ConfigurationPropertyAttribute
中包含空字符串并将 IsDefaultCollection 设置为 true。顺便说一句,我将我的配置放在一个外部文件中,如下所示:在这种情况下,我的 web.config 如下所示:
我想我会提到,以防其他人尝试将其添加到外部文件中(外部文件中的根级项与 web.config 中的外部化元素相同,这有点不直观)。
Since I spent a good amount of time on this, thought I'd add a real world example I just implemented in this commit: https://github.com/rhythmagency/formulate/commit/4d2a95e1a82eb6b3500ab0869b8f8b15bd3deaa9
Here was my goal for my web.config (which I was able to achieve):
This is the class for the highest-level "templates" configuration section:
Here's the next level down, the collection class:
And here's the deepest level class (the individual templates):
The important bit for me was to have the empty string in the
ConfigurationPropertyAttribute
and setting IsDefaultCollection to true. By the way, I put my config in an external file that looks like this:And in that case, my web.config looks like this:
Figured I'd mention that in case somebody else is trying to add it to an external file (it's somewhat non-intuitive that the root-level item in the external file is the same as the externalized element from the web.config).
您似乎缺少与此类似的内容,
有关详细信息,请参阅 http: //msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx
it seems you are missing something similar to this
for more information see http://msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx