自定义配置、配置元素和配置属性

14
我在网上搜索了三天,但没有找到任何关于这个问题的参考。我创建了一个自定义配置类用于我的app.config。一切都正常工作。问题出现在当配置元素的属性(不是必需的)未在app.config中定义时。似乎会返回配置属性的默认值。是否有人知道如何确定该属性在app.config中未定义?(我一直试图发布我的app.config,但不知道该怎么做...有人知道吗?)

//Main
namespace TestStub
{
    class Program
    {
        static void Main(string[] args)
        {
            CustomSettingsHandler config = (CustomSettingsHandler)ConfigurationManager.GetSection("CustomSettingsManager");
            Console.WriteLine("Setting1 {0}", config.Setting1.CustomSettingItem);
            Console.WriteLine("Setting2 {0}", config.Setting2.CustomSettingItem);
        }
    }
}

//Custom Configuration Class
namespace CustomConfiguration
{
    public class CustomSettingsHandler : ConfigurationSection
    {
        [ConfigurationProperty("setting1", IsRequired = false)]
        public CustomSettingElement Setting1 { get { return (CustomSettingElement)this["setting1"]; } }

        [ConfigurationProperty("setting2", IsRequired = false)]
        public CustomSettingElement Setting2 { get { return (CustomSettingElement)this["setting2"]; } }
    }

    public class CustomSettingElement : ConfigurationElement
    {
        [ConfigurationProperty("customsettingitem", IsRequired = false)]
        public int CustomSettingItem { get { return (int)this["customsettingitem"]; } }
    }
}
5个回答

11

我发现最好的方法是重写 ConfigurationSection.PostDeserialize() 并检查每个继承自 ConfigurationElement 的部分成员的 IsPresent 属性。

public class CustomSettingsHandler : ConfigurationSection
{
    // ...

    protected override void PostDeserialize()
    {
        foreach (ConfigurationProperty property in Properties)
        {
            var configElement = this[property] as ConfigurationElement;

            if (configElement != null 
                && !configElement.ElementInformation.IsPresent)
            {
                this[property] = null;
            }
        }

        base.PostDeserialize();
    }
}

每个未从配置文件中读取的 ConfigurationElement 在此之后将会是 null


顺便提一下,您不必在“PostDeserialize”事件中执行此操作。ElementInformation始终可用:Console.WriteLine("Setting1 {0}", config.Setting1.CustomSettingItem.ElementInformation.IsPresent ? "Y" : "N"); - Pedro Villa Verde

4
我能想到的两种方法是使用 DefaultValue,如下所示:
    [ConfigurationProperty("customsettingitem", DefaultValue = -1)]
    public int CustomSettingItem { get { return (int)this["customsettingitem"]; } }

假设存在一些无效的值。在这种情况下,CustomSettingItem == -1表示未设置,而>= 0是在配置中设置的值。当然,这假设-1在第一次输入时不是有效的输入。

第二个想法是使用可空的int:

    [ConfigurationProperty("customsettingitem", IsRequired = false)]
    public int? CustomSettingItem { get { return (int?)this["customsettingitem"]; } }

现在,如果配置中没有设置任何内容,则应该默认为null而不是0。

可以这样做,但我希望有一种方法可以在未定义属性时抑制默认值。我现在使用的解决方法是config.Setting2.IsPresent。 - user62064

2
尝试以下步骤:
configElement.ElementInformation.Properties[propName].ValueOrigin = 
        PropertyValueOrigin.SetHere

ValueOrigin 属性告诉您值来自哪里。


由于某些原因,“IsPresent”没有返回预期的值(对于所有内容都返回false)。 “ValueOrigin” 对我有用。 - atheaos

0
您也可以使用以下方式进行检查:
config.Setting1.CustomSettingItem.ElementInformation.IsPresent 

如果在您的配置文件中未找到它,它将返回false。


0

到目前为止,我还没有找到一种方法来告诉属性如果在配置文件中未定义则为空。微软似乎决定当你输入null时,你真正想要的是String.Empty或new ConfigurationElement()。

我目前解决这个问题的方式是这样的:

    bool _hasProp = true;
    protected override object OnRequiredPropertyNotFound(string name)
    {
        if (name == "prop")
        {
            _hasProp = false;
            return null; // note that this will still not make prop null
        }
        return base.OnRequiredPropertyNotFound(name);
    }

    [ConfigurationProperty("prop", IsRequired = true)]
    public string Prop
    {
        get { return _hasProp ? (string) this["prop"] : null; }
    }

这是一种hack方法,会错误地将属性标记为必需的。如果您正在使用工具编辑配置文件,则不建议使用此方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接