如何在app.config文件中创建嵌套的配置节?错误:“;无法识别的属性“;
本文关键字:错误 属性 识别 配置 app config 文件 嵌套 创建 | 更新日期: 2023-09-27 17:58:03
我需要创建一个嵌套的配置部分。问题是,我需要编写一个访问任意数量数据库的应用程序。这些可能是oracle、sql或其他任何东西。。。我想让我的配置部分看起来像这样:
<connectionconfigurations>
<databaseConnection dbname="connection1" dbsourceConnect="connectionstring1" provider="sql">
<sqlQueries>
<add name="querynumber1"
sqlFilePath="C:'Users'me'Desktop'sql"/>
<add name="querynumber2"
sqlFilePath="C:'Users'me'Desktop'sql"/>
</sqlQueries>
</databaseConnection>
<databaseConnection dbname="connection1" dbsourceConnect="connectionstring2" provider="oracle">
<sqlQueries>
<add name="querynumber3"
sqlFilePath="C:'Users'me'Desktop'oracle"/>
<add name="querynumber4"
sqlFilePath="C:'Users'me'Desktop'oracle"/>
</sqlQueries>
</databaseConnection>
</connectionconfigurations>
问题是我在访问所有参数时遇到了问题。如何创建这样的嵌套配置节并通过代码访问它们?
我制作了一个这样的类来处理连接部分:
public class Connectionconfigurations : ConfigurationSection
{
private static ConfigurationPropertyCollection _connectionConfiguration;
private static ConfigurationPropertyCollection _sqlQueries;
private static ConfigurationPropertyCollection _properties;
static Connectionconfigurations()
{
_connectionConfiguration = new ConfigurationProperty(
ConfigConstants.CONFIG_DATABASECONNECTION,
typeof(DatabaseConnectionElementCollection),
null,
ConfigurationPropertyOptions.IsRequired);
_sqlQueries = new ConfigurationProperty(
ConfigConstants.CONFIG_SQLQUERIES,
typeof(DatabaseConnectionElementCollection),
null,
ConfigurationPropertyOptions.IsRequired);
_properties = new ConfigurationPropertyCollection();
// Add other properties
_properties.Add(_databaseConnection);
}
[ConfigurationProperty("databaseConnection")]
public DatabaseConnectionElementCollection DatabaseConnection
{
get { return (DatabaseConnectionElementCollection)base[_databaseConnection]; }
}
}
然而,我得到了错误:"无法识别的属性‘dbname’。注意,属性名称区分大小写。"
DatabaseConnectionElement类:
public class DatabaseConnectionElement : ConfigurationElement
{
private static ConfigurationProperty _name;
private static ConfigurationProperty _sourceConnect;
private static ConfigurationProperty _provider;
private static SqlQueryElementCollection _sqlCollection; // Collection of sql queries for this DB element
private static ConfigurationPropertyCollection _properties;
static DatabaseConnectionElement()
{
_name = new ConfigurationProperty(ConfigConstants.CONFIG_DB_NAME, typeof(string), string.Empty,
ConfigurationPropertyOptions.IsKey);
_sourceConnect = new ConfigurationProperty(ConfigConstants.CONFIG_DB_SOURCECONNECT, typeof(string), string.Empty,
ConfigurationPropertyOptions.IsRequired);
_provider = new ConfigurationProperty(ConfigConstants.CONFIG_DB_PROVIDER, typeof(string), string.Empty,
ConfigurationPropertyOptions.IsRequired);
_sqlCollection = new SqlQueryElementCollection();
_properties = new ConfigurationPropertyCollection();
_properties.Add(_name);
_properties.Add(_sourceConnect);
_properties.Add(_reconnectDelay);
}
[ConfigurationProperty("dbname", IsKey = true)]
public string Name
{
get
{
return (string)base[_name];
}
}
[ConfigurationProperty("dbsourceConnect", IsRequired = true)]
public string SourceConnect
{
get
{
return (string)base[_sourceConnect];
}
}
[ConfigurationProperty("provider", IsRequired = true)]
public string Provider
{
get
{
return (string)base[_provider];
}
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return _properties;
}
}
}
我认为这可能会有所帮助。我创建了一个具有子元素列表的通用配置部分。我只是把它们叫做元素。你可以随便叫他们。
/// <summary>
/// Defines a generic custom configuration section with a collection of elements of type T.
/// Reference: http://www.abhisheksur.com/2011/09/writing-custom-configurationsection-to.html
/// </summary>
public class GenericSection<T> : ConfigurationSection
where T : ConfigurationElement, IConfigurationElement, new()
{
// Attribute argument must be a constant expression.
protected const string _elementsTag = "elements";
public GenericSection()
{
}
[ConfigurationProperty(_elementsTag, Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public GenericElementCollection<T> Elements
{
get { return ((GenericElementCollection<T>)(base[_elementsTag])); }
set { base[_elementsTag] = value; }
}
}
这是Generic Element集合。
/// <summary>
/// Defines a generic ConfigurationElementCollection
/// </summary>
[ConfigurationCollection(typeof(IConfigurationElement))]
public class GenericElementCollection<T> : ConfigurationElementCollection
where T : ConfigurationElement, IConfigurationElement, new()
{
internal const string _elementName = "elements";
protected override string ElementName
{
get { return _elementName; }
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.AddRemoveClearMap; }
}
protected override bool IsElementName(string elementName)
{
return elementName.Equals(_elementName, StringComparison.InvariantCultureIgnoreCase);
}
public override bool IsReadOnly()
{
return false;
}
protected override ConfigurationElement CreateNewElement()
{
return new T();
}
/// <summary>
/// Return key value for element.
/// </summary>
/// <param name="element"></param>
/// <returns></returns>
/// <remarks></remarks>
protected override object GetElementKey(ConfigurationElement element)
{
return ((T)element).Name;
}
/// <summary>
/// Default index property.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T this[int index] // #c160704 was IConfigruationElement
{
get { return (T)BaseGet(index); }
}
/// <summary>
/// Returns content element by name.
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public T GetElementByName(string name)
{
return (T)BaseGet(name);
}
public IEnumerable<T> Elements
{
get
{
for (int index = 0; index < this.Count; index++) yield return (T)BaseGet(index);
}
}
/// <summary>
/// Add an element to the collection
/// </summary>
/// <param name="element"></param>
public void AddElement(T element)
{
BaseAdd(element);
}
}
这是我为元素使用的接口。它要求元素具有Name属性和活动标志。
public interface IConfigurationElement
{
string Name { get; set; }
bool Active { get; set; }
}
下面是一个实例化并使用泛型创建具有文件夹列表的配置部分的示例。
使用元素类型实例化GenericSection。
/// <summary>
/// Defines a custom configuration section for folder elements.
/// Reference: http://www.abhisheksur.com/2011/09/writing-custom-configurationsection-to.html
/// </summary>
public class FolderSection : GenericSection<FolderElement>
{
// This section doesn't require any addition properties.
}
我们不需要对GenericElementCollection做任何事情。
这是FolderElement:
/// <summary>
/// Defines a configuration folder
/// </summary>
public class FolderElement : ConfigurationElement, IConfigurationElement
{
protected const string NameKey = "name";
protected const string VolumeKey = "volume";
protected const string PathKey = "path";
[ConfigurationProperty(NameKey, DefaultValue = "", IsKey = true, IsRequired = true)]
public string Name
{
get { return (string)base[NameKey]; }
set { base[NameKey] = value; }
}
[ConfigurationProperty(VolumeKey, DefaultValue = "", IsKey = false, IsRequired = false)]
public string VolumeLabel
{
get { return (string)base[VolumeKey]; }
set { base[VolumeKey] = value; }
}
[ConfigurationProperty(PathKey, DefaultValue = "", IsKey = false, IsRequired = true)]
public string Path
{
get { return (string)base[PathKey]; }
set { base[PathKey] = value; }
}
[ConfigurationProperty("active", DefaultValue = "true", IsKey = false, IsRequired = false)]
public bool Active
{
get { return (bool)base["active"]; }
set { base["active"] = value; }
}
}
以下是我的App.config的样子。我有两个文件夹部分。
<configuration>
<configSections>
<section name="recent-folders" type="Common.Config.FolderSection, Common.Core"/>
<section name="hidden-folders" type="Common.Config.FolderSection, Common.Core"/>
</configSections>
...
<hidden-folders>
<elements>
<add name="folder1" volume="OS" path="C:'some'hidden'path" />
<add name="folder2" volume="OS" path="C:'some'other'hidden'path" />
</elements>
</hidden-folders>
<recent-folders>
<elements>
<add name="folder1" volume="OS" path="C:'Some'path" />
<add name="folder2" volume="OS" path="C:'Some'other'path" />
</elements>
</recent-folders>
</configururation>