【问题标题】:Custom config section with non-ConfigurationElement properties具有非 ConfigurationElement 属性的自定义配置部分
【发布时间】:2016-11-07 08:18:10
【问题描述】:

我有一个有效的自定义配置部分。但是,通过ConfigurationElementCollection 获取我的数据很痛苦,但是当我尝试将我的属性实现为 IEnumerable 时,它​​会失败并出现错误:

ConfigurationErrorsException 未处理“属性 'contacts' 不是 ConfigurationElement。"

这是导致失败的代码:

[ConfigurationProperty("contacts", IsDefaultCollection = false)]
public IEnumerable<string> Contacts
{
    get { return ((ContactCollection)base["contacts"]).Cast<ContactElement>().Select(x => x.Address); }
}

但是,如果我将其更改为:

[ConfigurationProperty("contacts", IsDefaultCollection = false)]
public ContactCollection Contacts
{
    get { return ((ContactCollection)base["contacts"]); }
}

一切正常。 This 的答案听起来像是微软决定不允许的事情,所以我不能拥有除 ConfigurationElement 之外的任何类型的属性。真的是这样吗?如何将我的属性实现为 IEnumerable&lt;string&gt;

如果这很重要,我正在尝试存储电子邮件,并且我希望为每个电子邮件添加一个元素,因为它们可能有很多,我们可能希望将来存储有关每个联系人的更多信息,而且我认为一个逗号分隔的列表可能会变得丑陋。例如,类似:

<emergency>
    <contact address="sirdank@stackoverflow.com" />
    <contact address="jon.skeet@stackoverflow.com" />
</emergency>

或者

<emergency>
    <contact>sirdank@stackoverflow.com</contact>
    <contact>jon.skeet@stackoverflow.com</contact>
</emergency>

谢谢!

【问题讨论】:

标签: c# linq configuration configurationmanager


【解决方案1】:

提供两种方法有什么害处吗?第一个满足 Microsoft 要求,第二个满足您自己的要求。

    public IEnumerable<string> Contacts
    {
        get
        {
            return ContactCollection.Cast<ContactElement>().Select(x => x.Address);     
        }
    }

    [ConfigurationProperty("contacts", IsDefaultCollection = false)]
    public ContactCollection ContactCollection
    {
        get { return ((ContactCollection)base["contacts"]); }
    }

【讨论】:

  • 我想避免这样做,但我不知道为什么有人反对你。如果这是唯一的解决方案,我将来会接受。另外,感谢您在这里工作五年后的第一次回答! :)
  • 请注意,如果您想从调用者和智能感知中屏蔽该属性,您甚至可以将 ContactCollection 声明为私有,这很有趣。
  • 大声笑...我的第一个答案,我立即被否决了!我害怕是明智的;)
  • 虽然对我来说,对这个解决方案的需求似乎很愚蠢,但使用 private 修饰符,它的效果和我希望的一样好。谢谢!
【解决方案2】:

如果您只需要一个字符串列表,一个解决方案是声明一个逗号分隔(或任何分隔符)的值列表,如下所示:

    [ConfigurationProperty("contacts")]
    [TypeConverter(typeof(StringSplitConverter))]
    public IEnumerable<string> Contacts
    {
        get
        {
            return (IEnumerable<string>)base["contacts"];
        }
    }

有了这个TypeConverter 类:

public class StringSplitConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return string.Format("{0}", value).Split(',');
    }
}

然后您的 .config 文件将简单地声明如下:

<configuration>
  ...
  <mySection contacts="bill,joe" />
  ...
</configuration>

请注意,这不适用于集合,当您总是需要明确声明一个属性时,就像在 Will 的回答中一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 2023-03-26
    • 2010-10-25
    相关资源
    最近更新 更多