使用 ConfigurationSection / ConfigurationElementCollection 从 web.config 创建一个嵌套的项目集合
Use ConfigurationSection / ConfigurationElementCollection to create a nested collection of items from web.config
我正在尝试在 web.config 中创建自定义分区组。它主要工作,但因以下错误而失败:
Unrecognized element 'add'. (web.config line 736) at
System.Configuration.BaseConfigurationRecord.EvaluateOne(String[]
keys, SectionInput input, Boolean isTrusted, FactoryRecord
factoryRecord, SectionRecord sectionRecord, Object parentResult)....
代码中可能还有其他错误,但这是我无法通过的部分。
这是我的 web.config XML:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="systemEmailsGroup">
<section name="systemEmails" type="SystemEmailsConfiguration" />
</sectionGroup>
</configSections>
<!-- lots of other stuff -->
<systemEmailsGroup>
<systemEmails>
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<add name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06" />
<!-- ^^^ LINE 736 ^^^ -->
<add name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<add name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</emails>
</systemEmails>
</systemEmailsGroup>
</configuration>
注意我把错误中提到的第736行标出来了
我的 class 结构如下。第一个继承ConfigurationSection
,第二个继承ConfigurationElementCollection
,最后一个继承ConfigurationElement
。之后是 SystemEmailsElement
类型的扩展 class。它可能与错误无关,但为了完成起见,我将其包括在内。
public class SystemEmailsConfiguration : ConfigurationSection
{
public static SystemEmailsConfiguration GetConfig()
{
return ConfigurationManager.GetSection("systemEmailsGroup/systemEmails") as SystemEmailsConfiguration;
}
[ConfigurationProperty("emails", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(SystemEmailsElementCollection),
AddItemName = "email", ClearItemsName = "clear", RemoveItemName = "remove")]
public SystemEmailsElementCollection Emails
{
get
{
return base["emails"] as SystemEmailsElementCollection;
}
}
}
public enum SystemEmailsSource
{
None = 0,
UserName = 1,
RoleName = 2,
Group = 3
}
public class SystemEmailsElementCollection : ConfigurationElementCollection, IEnumerable<SystemEmailsElement>
{
List<SystemEmailsElement> _elements = new List<SystemEmailsElement>();
public SystemEmailsElement this[int index]
{
get
{
return _elements[index];
}
set
{
if (index >= 0 && index < _elements.Count)
{
_elements.RemoveAt(index);
}
_elements.Insert(index, value);
}
}
public SystemEmailsElement this[string key]
{
get
{
return _elements.Where(e => e.Name == key).FirstOrDefault();
}
set
{
var el = _elements.Where(e => e.Name == key).FirstOrDefault();
if (el != null)
{
int index = _elements.IndexOf(el);
_elements.RemoveAt(index);
_elements.Insert(index, value);
}
else
_elements.Add(value);
}
}
protected override ConfigurationElement CreateNewElement()
{
var el = new SystemEmailsElement();
_elements.Add(el);
return el;
}
protected override object GetElementKey(ConfigurationElement element)
{
return _elements.Find(e => e.Equals(element)).Name;
}
public new IEnumerator<SystemEmailsElement> GetEnumerator()
{
return _elements.GetEnumerator();
}
}
public class SystemEmailsElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get
{
return this["name"] as string;
}
}
[ConfigurationProperty("source", DefaultValue = SystemEmailsSource.None)]
public SystemEmailsSource Source
{
get
{
return (this["source"] != null) ? (SystemEmailsSource)this["source"] : SystemEmailsSource.None;
}
}
[ConfigurationProperty("defaultAddress")]
public string DefaultAddress
{
get
{
return this["defaultAddress"] as string;
}
}
[ConfigurationProperty("defaultName")]
public string DefaultName
{
get
{
return this["defaultName"] as string;
}
}
[ConfigurationProperty("defaultEmailName")]
public string DefaultEmailName
{
get
{
return this["defaultEmailName"] as string;
}
}
[ConfigurationProperty("username")]
public string UserName
{
get
{
return this["username"] as string;
}
}
[ConfigurationProperty("rolename")]
public string RoleName
{
get
{
return this["rolename"] as string;
}
}
[ConfigurationProperty("email")]
[ConfigurationCollection(typeof(SystemEmailsElementCollection),
AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
public SystemEmailsElementCollection Emails
{
get
{
return base["email"] as SystemEmailsElementCollection;
}
}
}
public static class SystemEmailsElementExtenstions
{
/// <summary>
/// Returns true if the SystemEmailsElement may contain a group of email addresses.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsGroup(this SystemEmailsElement value)
{
return (value.Source == SystemEmailsSource.Group || value.Source == SystemEmailsSource.RoleName);
}
/// <summary>
/// Gets the email or emails result of this section as a MailAddressCollection.
/// Returns an empty MailAddressCollection if not able to create any MailAddress objects.
/// </summary>
/// <returns></returns>
public static MailAddressCollection GetEmails(this SystemEmailsElement value)
{
var emails = new MailAddressCollection();
MailAddress eml = null;
if (value.IsGroup())
{
switch (value.Source)
{
case SystemEmailsSource.RoleName:
if (value.RoleName != null)
{
foreach (UsersNames user in AppPublic.GetUsersByRole(value.RoleName))
{
eml = AppPublic.GetEmailByUserID(user.UserId);
if (eml != null)
emails.Add(eml);
}
}
break;
default: //Group
foreach (var el in value.Emails)
{
foreach (MailAddress e in el.GetEmails())
emails.Add(e);
}
break;
}
}
else
{
emails.Add(value.GetEmail());
}
if (emails.Count == 0)
{
eml = value.CreateEmailFromDefaults();
if (eml != null)
emails.Add(eml);
}
return emails;
}
/// <summary>
/// Gets the email result of this section or the first item in a group as a MailAddress object.
/// Returns null if not able to create the MailAddress.
/// </summary>
/// <returns></returns>
public static MailAddress GetEmail(this SystemEmailsElement value)
{
if (value.IsGroup())
{
return value.GetEmails().FirstOrDefault();
}
else
{
MailAddress eml = null;
if (value.Source == SystemEmailsSource.UserName)
{
if (value.UserName != null)
eml = AppPublic.GetEmailByUserName(value.UserName);
}
if (eml == null)
eml = CreateEmailFromDefaults(value);
return eml;
}
}
/// <summary>
/// Creates a mail address object using the default attribute values from the SystemEmailElement.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static MailAddress CreateEmailFromDefaults(this SystemEmailsElement value)
{
MailAddress eml = null;
//DefaultEmailName takes precedence.
if (value.DefaultEmailName != null)
{
var el = SystemEmailsConfiguration.GetConfig().Emails[value.DefaultEmailName];
if (el != null)
eml = el.GetEmail();
}
//Fall back to DefaultAddress.
if (eml == null && value.DefaultAddress != null)
{
if (value.DefaultName == null)
eml = new MailAddress(value.DefaultAddress);
else
eml = new MailAddress(value.DefaultAddress, value.DefaultName);
}
return eml;
}
}
在理想世界中,<add>
节点将重命名为 <email>
节点,并且此代码将是递归的并允许任意(理论上)数量的节点深度。
但是,如果我能让第一个 <add>
级别正常工作,那就太好了。几个小时以来,我一直在努力寻找属性、签名、XML 等的正确组合。
谢谢!!
要修复您的即时错误,您只需将包装 <email>
标记添加到您的 <add/>
元素。那是因为你的 SystemEmailsElement
包含 Emails
属性 这是根标签定义为 "email" 的集合(通过 [ConfigurationProperty("email")]
)。像这样:
<systemEmails>
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<email>
<add name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06" />
<!-- ^^^ LINE 736 ^^^ -->
<add name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<add name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</email>
</emails>
</systemEmails>
现在,要使其像理想世界一样工作,您可以像这样利用 ConfigurationProperty
属性的 IsDefaultCollection
属性:
[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof (SystemEmailsElementCollection),
AddItemName = "email")]
public SystemEmailsElementCollection Emails
{
get { return base[""] as SystemEmailsElementCollection; }
}
这将允许您按照您期望的方式创建递归电子邮件节点:
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<email name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06">
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
</email>
<!-- ^^^ LINE 736 ^^^ -->
<email name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<email name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</emails>
我正在尝试在 web.config 中创建自定义分区组。它主要工作,但因以下错误而失败:
Unrecognized element 'add'. (web.config line 736) at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)....
代码中可能还有其他错误,但这是我无法通过的部分。
这是我的 web.config XML:
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="systemEmailsGroup">
<section name="systemEmails" type="SystemEmailsConfiguration" />
</sectionGroup>
</configSections>
<!-- lots of other stuff -->
<systemEmailsGroup>
<systemEmails>
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<add name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06" />
<!-- ^^^ LINE 736 ^^^ -->
<add name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<add name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</emails>
</systemEmails>
</systemEmailsGroup>
</configuration>
注意我把错误中提到的第736行标出来了
我的 class 结构如下。第一个继承ConfigurationSection
,第二个继承ConfigurationElementCollection
,最后一个继承ConfigurationElement
。之后是 SystemEmailsElement
类型的扩展 class。它可能与错误无关,但为了完成起见,我将其包括在内。
public class SystemEmailsConfiguration : ConfigurationSection
{
public static SystemEmailsConfiguration GetConfig()
{
return ConfigurationManager.GetSection("systemEmailsGroup/systemEmails") as SystemEmailsConfiguration;
}
[ConfigurationProperty("emails", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(SystemEmailsElementCollection),
AddItemName = "email", ClearItemsName = "clear", RemoveItemName = "remove")]
public SystemEmailsElementCollection Emails
{
get
{
return base["emails"] as SystemEmailsElementCollection;
}
}
}
public enum SystemEmailsSource
{
None = 0,
UserName = 1,
RoleName = 2,
Group = 3
}
public class SystemEmailsElementCollection : ConfigurationElementCollection, IEnumerable<SystemEmailsElement>
{
List<SystemEmailsElement> _elements = new List<SystemEmailsElement>();
public SystemEmailsElement this[int index]
{
get
{
return _elements[index];
}
set
{
if (index >= 0 && index < _elements.Count)
{
_elements.RemoveAt(index);
}
_elements.Insert(index, value);
}
}
public SystemEmailsElement this[string key]
{
get
{
return _elements.Where(e => e.Name == key).FirstOrDefault();
}
set
{
var el = _elements.Where(e => e.Name == key).FirstOrDefault();
if (el != null)
{
int index = _elements.IndexOf(el);
_elements.RemoveAt(index);
_elements.Insert(index, value);
}
else
_elements.Add(value);
}
}
protected override ConfigurationElement CreateNewElement()
{
var el = new SystemEmailsElement();
_elements.Add(el);
return el;
}
protected override object GetElementKey(ConfigurationElement element)
{
return _elements.Find(e => e.Equals(element)).Name;
}
public new IEnumerator<SystemEmailsElement> GetEnumerator()
{
return _elements.GetEnumerator();
}
}
public class SystemEmailsElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get
{
return this["name"] as string;
}
}
[ConfigurationProperty("source", DefaultValue = SystemEmailsSource.None)]
public SystemEmailsSource Source
{
get
{
return (this["source"] != null) ? (SystemEmailsSource)this["source"] : SystemEmailsSource.None;
}
}
[ConfigurationProperty("defaultAddress")]
public string DefaultAddress
{
get
{
return this["defaultAddress"] as string;
}
}
[ConfigurationProperty("defaultName")]
public string DefaultName
{
get
{
return this["defaultName"] as string;
}
}
[ConfigurationProperty("defaultEmailName")]
public string DefaultEmailName
{
get
{
return this["defaultEmailName"] as string;
}
}
[ConfigurationProperty("username")]
public string UserName
{
get
{
return this["username"] as string;
}
}
[ConfigurationProperty("rolename")]
public string RoleName
{
get
{
return this["rolename"] as string;
}
}
[ConfigurationProperty("email")]
[ConfigurationCollection(typeof(SystemEmailsElementCollection),
AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")]
public SystemEmailsElementCollection Emails
{
get
{
return base["email"] as SystemEmailsElementCollection;
}
}
}
public static class SystemEmailsElementExtenstions
{
/// <summary>
/// Returns true if the SystemEmailsElement may contain a group of email addresses.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static bool IsGroup(this SystemEmailsElement value)
{
return (value.Source == SystemEmailsSource.Group || value.Source == SystemEmailsSource.RoleName);
}
/// <summary>
/// Gets the email or emails result of this section as a MailAddressCollection.
/// Returns an empty MailAddressCollection if not able to create any MailAddress objects.
/// </summary>
/// <returns></returns>
public static MailAddressCollection GetEmails(this SystemEmailsElement value)
{
var emails = new MailAddressCollection();
MailAddress eml = null;
if (value.IsGroup())
{
switch (value.Source)
{
case SystemEmailsSource.RoleName:
if (value.RoleName != null)
{
foreach (UsersNames user in AppPublic.GetUsersByRole(value.RoleName))
{
eml = AppPublic.GetEmailByUserID(user.UserId);
if (eml != null)
emails.Add(eml);
}
}
break;
default: //Group
foreach (var el in value.Emails)
{
foreach (MailAddress e in el.GetEmails())
emails.Add(e);
}
break;
}
}
else
{
emails.Add(value.GetEmail());
}
if (emails.Count == 0)
{
eml = value.CreateEmailFromDefaults();
if (eml != null)
emails.Add(eml);
}
return emails;
}
/// <summary>
/// Gets the email result of this section or the first item in a group as a MailAddress object.
/// Returns null if not able to create the MailAddress.
/// </summary>
/// <returns></returns>
public static MailAddress GetEmail(this SystemEmailsElement value)
{
if (value.IsGroup())
{
return value.GetEmails().FirstOrDefault();
}
else
{
MailAddress eml = null;
if (value.Source == SystemEmailsSource.UserName)
{
if (value.UserName != null)
eml = AppPublic.GetEmailByUserName(value.UserName);
}
if (eml == null)
eml = CreateEmailFromDefaults(value);
return eml;
}
}
/// <summary>
/// Creates a mail address object using the default attribute values from the SystemEmailElement.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static MailAddress CreateEmailFromDefaults(this SystemEmailsElement value)
{
MailAddress eml = null;
//DefaultEmailName takes precedence.
if (value.DefaultEmailName != null)
{
var el = SystemEmailsConfiguration.GetConfig().Emails[value.DefaultEmailName];
if (el != null)
eml = el.GetEmail();
}
//Fall back to DefaultAddress.
if (eml == null && value.DefaultAddress != null)
{
if (value.DefaultName == null)
eml = new MailAddress(value.DefaultAddress);
else
eml = new MailAddress(value.DefaultAddress, value.DefaultName);
}
return eml;
}
}
在理想世界中,<add>
节点将重命名为 <email>
节点,并且此代码将是递归的并允许任意(理论上)数量的节点深度。
但是,如果我能让第一个 <add>
级别正常工作,那就太好了。几个小时以来,我一直在努力寻找属性、签名、XML 等的正确组合。
谢谢!!
要修复您的即时错误,您只需将包装 <email>
标记添加到您的 <add/>
元素。那是因为你的 SystemEmailsElement
包含 Emails
属性 这是根标签定义为 "email" 的集合(通过 [ConfigurationProperty("email")]
)。像这样:
<systemEmails>
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<email>
<add name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06" />
<!-- ^^^ LINE 736 ^^^ -->
<add name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<add name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</email>
</emails>
</systemEmails>
现在,要使其像理想世界一样工作,您可以像这样利用 ConfigurationProperty
属性的 IsDefaultCollection
属性:
[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof (SystemEmailsElementCollection),
AddItemName = "email")]
public SystemEmailsElementCollection Emails
{
get { return base[""] as SystemEmailsElementCollection; }
}
这将允许您按照您期望的方式创建递归电子邮件节点:
<emails>
<email name="SystemEmail01" defaultAddress="SystemEmail01@email.com" defaultName="John Doe 01" />
<email name="SystemEmail02" source="UserName" username="Username02" defaultAddress="SystemEmail02@email.com" defaultName="Jane Doe 02" />
<email name="SystemEmail03" defaultAddress="SystemEmail03@email.com" defaultName="John Doe 03" />
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
<email name="SystemEmailGroup01" source="Group">
<email name="SystemEmail06" defaultAddress="SystemEmail06@email.com" defaultName="Jane Doe 06">
<email name="SystemEmail04" source="UserName" username="Username04" />
<email name="SystemEmail05" source="RoleName" rolename="administrators" defaultEmailName="SystemEmail02" />
</email>
<!-- ^^^ LINE 736 ^^^ -->
<email name="SystemEmail07" defaultAddress="SystemEmail07@email.com" defaultName="John Doe 07" />
<email name="SystemEmail08" defaultAddress="SystemEmail08@email.com" defaultName="Jane Doe 08" />
</email>
</emails>