【问题标题】:Custom Configuration, ConfigurationElements, and ConfigurationProperties自定义配置、ConfigurationElements 和 ConfigurationProperties
【发布时间】:2016-05-27 06:36:22
【问题描述】:

过去 3 天我一直在网上搜索,但找不到任何有关此问题的参考资料。我创建了一个自定义配置类以与我的 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"]; } }
    }
}

【问题讨论】:

    标签: c# app-config configurationsection configurationelement


    【解决方案1】:

    我发现最好的方法是覆盖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");
    【解决方案2】:

    我能想到的两件事就是使用 DefaultValue,如下所示:

        [ConfigurationProperty("customsettingitem", DefaultValue = -1)]
        public int CustomSettingItem { get { return (int)this["customsettingitem"]; } }
    

    假设有一些无效的值。在这种情况下,CustomSettingItem == -1 表示未设置,>= 0 是在 config.xml 中设置的值。当然,这首先假设 -1 不是有效的输入。

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

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

    现在如果没有在配置中设置,它应该默认为 null 而不是 0。

    【讨论】:

    • 这行得通,但我希望有一种方法可以在未定义属性时抑制默认值。我现在使用的解决方法是 config.Setting2.IsPresent
    【解决方案3】:

    尝试以下方法:

    configElement.ElementInformation.Properties[propName].ValueOrigin = 
            PropertyValueOrigin.SetHere
    

    ValueOrigin 属性告诉您值​​从何而来。

    【讨论】:

    • IsPresent 由于某种原因没有返回预期值(它对所有内容都返回 false)。 ValueOrigin 为我工作。
    【解决方案4】:

    到目前为止,如果一个属性没有在配置文件中定义,我还不能告诉它为空。微软似乎在它的无限智慧中确定您在键入 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; }
        }
    

    这是一种黑客行为,会错误地按要求标记属性。如果您使用工具来编辑配置文件,则不会这样。

    【讨论】:

      【解决方案5】:

      您还可以使用以下方法进行检查:

      config.Setting1.CustomSettingItem.ElementInformation.IsPresent 
      

      如果在您的配置文件中找不到它,它会给您错误。

      【讨论】:

        猜你喜欢
        • 2018-01-27
        • 1970-01-01
        • 2011-10-02
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-27
        相关资源
        最近更新 更多