Ron*_*erg 10 .net c# system.configuration .net-4.0
我正在尝试为.NET4应用程序编写一个非常简单的自定义配置部分.我的目标是:
<configuration>
<configSections>
<section name="myServices" type="My.ConfigSection, My.Assembly" />
</configSections>
<myServices>
<add name="First" />
<add name="Second" />
</myServices>
</configuration>
Run Code Online (Sandbox Code Playgroud)
但是,ConfigurationErrorsException
当我打电话时,我不断得到:'无法识别的元素'添加'' ConfigurationManager.GetSection("myServices")
.我已经盯着它看了一段时间,但还没弄明白我做错了什么.以下是我的代码.这是三大类: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; } }
}
Run Code Online (Sandbox Code Playgroud)
接下来,集合类本身.它是类型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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后是集合中元素的类.目前,这个类有一个属性,但稍后会有更多(这阻止我使用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; } }
}
Run Code Online (Sandbox Code Playgroud)
Ron*_*erg 12
好吧,我发现了看似随意的修复.而不是这个:
[ConfigurationProperty("", IsDefaultCollection = true)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }
Run Code Online (Sandbox Code Playgroud)
你应该使用:
[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }
Run Code Online (Sandbox Code Playgroud)
不知道两者之间有什么区别.对我来说,它们看起来非常相似......或者至少,没有任何关于为什么一个人优先于另一个人的建议.
由于我在这方面花了很多时间,所以我想添加一个我刚刚在这次提交中实现的真实世界示例:https ://github.com/rhythmagency/formulate/commit/4d2a95e1a82eb6b3500ab0869b8f8b15bd3deaa9
这是我的 web.config 目标(我能够实现):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="formulateConfiguration">
<section name="templates" type="formulate.app.Configuration.TemplatesConfigSection, formulate.app" requirePermission="false"/>
</sectionGroup>
</configSections>
<formulateConfiguration>
<templates>
<template name="Responsive" path="~/Views/Formulate/Responsive.Bootstrap.Angular.cshtml" />
</templates>
</formulateConfiguration>
</configuration>
Run Code Online (Sandbox Code Playgroud)
这是最高级别“模板”配置部分的类:
namespace formulate.app.Configuration
{
// Namespaces.
using System.Configuration;
/// <summary>
/// A configuration section for Formulate templates.
/// </summary>
public class TemplatesConfigSection : ConfigurationSection
{
#region Properties
/// <summary>
/// The templates in this configuration section.
/// </summary>
[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(TemplateCollection), AddItemName = "template")]
public TemplateCollection Templates
{
get
{
return base[""] as TemplateCollection;
}
}
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
这是下一个级别,集合类:
namespace formulate.app.Configuration
{
// Namespaces.
using System.Configuration;
/// <summary>
/// A collection of templates from the configuration.
/// </summary>
[ConfigurationCollection(typeof(TemplateElement))]
public class TemplateCollection : ConfigurationElementCollection
{
#region Methods
/// <summary>
/// Creates a new template element.
/// </summary>
/// <returns>The template element.</returns>
protected override ConfigurationElement CreateNewElement()
{
return new TemplateElement();
}
/// <summary>
/// Gets the key for an element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns>The key.</returns>
protected override object GetElementKey(ConfigurationElement element)
{
return (element as TemplateElement).Name;
}
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
这是最深层的类(各个模板):
namespace formulate.app.Configuration
{
// Namespaces.
using System.Configuration;
/// <summary>
/// A "template" configuration element.
/// </summary>
public class TemplateElement : ConfigurationElement
{
#region Constants
private const string DefaultPath = "~/*Replace Me*.cshtml";
#endregion
#region Properties
/// <summary>
/// The name of the template.
/// </summary>
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get
{
return base["name"] as string;
}
set
{
this["name"] = value;
}
}
/// <summary>
/// The path to this template.
/// </summary>
/// <remarks>
/// Should start with "~" and end with ".cshtml".
/// </remarks>
[ConfigurationProperty("path", IsRequired = true, DefaultValue = DefaultPath)]
[RegexStringValidator(@"^~.*\.[cC][sS][hH][tT][mM][lL]$")]
public string Path
{
get
{
var result = base["path"] as string;
return result == DefaultPath ? null : result;
}
set
{
this["path"] = value;
}
}
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
对我来说重要的一点是在 中包含空字符串ConfigurationPropertyAttribute
并将 IsDefaultCollection 设置为 true。顺便说一下,我将配置放在一个外部文件中,如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<templates>
<template name="Responsive" path="~/Views/Formulate/Responsive.Bootstrap.Angular.cshtml" />
</templates>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我的 web.config 看起来像这样:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="formulateConfiguration">
<section name="templates" type="formulate.app.Configuration.TemplatesConfigSection, formulate.app" requirePermission="false"/>
</sectionGroup>
</configSections>
<formulateConfiguration>
<templates configSource="config\Formulate\templates.config"/>
</formulateConfiguration>
</configuration>
Run Code Online (Sandbox Code Playgroud)
我想我会提到,以防其他人尝试将其添加到外部文件中(外部文件中的根级项目与 web.config 中的外部化元素相同,这有点不直观)。
归档时间: |
|
查看次数: |
10851 次 |
最近记录: |