我有以下ConfigurationProperty作为元素的一部分:
[ConfigurationProperty("example", IsRequired = false, DefaultValue = null)]
public string Example {
get { return (string)base["example"]; }
set { base["example"] = value; }
}
如果我按以下方式设置它,它将接受"Hello"
字符串并正常工作:
<myElement example="Hello"/>
如果它不存在,我会遇到一些问题:
<myElement/>
它不像上面指定的那样接受null
的默认值,而是接受String.Empty
。为什么是这样,以及如何使它具有null
的默认值。
更新
这肯定是因为base["example"]
返回String.Empty
,其中base
是一个ConfigurationElement
(索引器在这里定义为:https://msdn.microsoft.com/en-us/library/c8693ks1(v=vs.110).aspx,但我仍然不确定它为什么不接受null
的值。
更新
甚至DefaultValue = default(string)
也将字符串设置为String.Empty
。
更新
如果配置中不存在属性,甚至base.Properties.Contains("example")
也会返回true
。
发布于 2015-04-24 09:55:23
从班级判断,这可能不是一个bug,而是一个特性。
下面是相关的内部方法InitDefaultValueFromTypeInfo
(我做了一些小的格式修改):
私有void InitDefaultValueFromTypeInfo(ConfigurationPropertyAttribute attribProperty,DefaultValueAttribute attribStdDefault) { object defaultValue = attribProperty.DefaultValue;//如果没有默认值--尝试另一个属性( clr标准属性) if ((defaultValue == null DefaultValueAttribute defaultValue == ConfigurationElement.s_nullPropertyValue) & (attribStdDefault =null){ defaultValue = attribStdDefault.Value;} //如果支柱属性中有默认值-检查是否需要从string if ((defaultValue != null) & (defaultValue是string) & (_type != typeof(String){/使用转换器来解析该属性默认值,尝试{ defaultValue =defaultValue} catch (异常ex) {抛出新的ConfigurationErrorsException(SR.GetString(SR.Default_value_conversion_error_from_string,_name,ex.Message);} if (defaultValue == null == ConfigurationElement.s_nullPropertyValue) { if (_type == typeof(string)) { defaultValue = String.Empty;}否则if (_type.IsValueType) { defaultValue =defaultValue} SetDefaultValue(defaultValue);}
最后一个if
块很有趣:如果属性的类型为string
,默认值为null
,则默认值将更改为string.Empty
。
第一个if
块暗示了对这种奇怪行为的可能解释。[ConfigurationProperty]
属性的DefaultValue
属性是可选的。如果程序员没有设置DefaultValue
,那么它本身就是默认的null
。第一个if
块使用默认的null
来检查是否指定了DefaultValue
。如果不是,则返回到从[DefaultValue]
属性中获取默认值(如果存在的话)。
这意味着:指定DefaultValue = null
与根本不指定它具有相同的效果,在这种情况下,配置子系统为字符串选择一个"sane“默认值:空字符串。
解决办法:
这里有一个有点麻烦的解决方案:不要将您的配置属性声明为string
,而是将其声明为字符串的瘦包装类型;然后声明一个合适的类型转换器:
[ConfigurationProperty("name", IsRequired = false)]
[TypeConverter(typeof(IncognitoStringConverter))] // note: additional attribute!
public IncognitoString Name // note: different property type
{
get
{
return (IncognitoString)base["name"];
}
set
{
base["name"] = value;
}
}
下面是IncognitoString
和IncognitoStringConverter
的实现
public struct IncognitoString
{
private IncognitoString(string value)
{
this.value = value;
}
private readonly string value;
public static implicit operator IncognitoString(string value)
{
return new IncognitoString(value);
}
public static implicit operator string(IncognitoString incognitoString)
{
return incognitoString.value;
}
… // perhaps override ToString, GetHashCode, and Equals as well.
}
public sealed class IncognitoStringConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return (IncognitoString)(string)value;
}
}
因为IncognitoString
隐式可转换为string
,所以可以将属性值赋值给任何字符串变量。我知道,仅仅为了获得可空的属性,这是非常困难和复杂的。也许只是活在空的绳子里。
发布于 2016-03-03 04:44:58
另一个解决办法是打这样的电话:
[ConfigurationProperty("Prompt")]
public string Prompt
{
get { return this.GetNullableStringValue("Prompt"); }
}
private string GetNullableStringValue(string propertyName)
{
return (string)this[new ConfigurationProperty(propertyName, typeof(string), null)];
}
像这样调用GetNullableString
会绕过configuration属性属性,并停止它将DefaultValue默认为null。您也可以将该方法放在基类中,以使其更加整洁。
您只需记住,如果您想要更改默认设置,您将调用它。
如果您想要删除可能在属性上定义的其他一些内容,也可以对this.ElementInformation.Properties[propertyName]
进行调用--只是不要使用它来填充DefaultValue
发布于 2017-03-15 05:04:34
与检查null
的属性值不同,您可以轻松地检查属性是否已在配置文件中设置或默认值是否已返回。这是可以做的,看看ValueOrigin
在ConfigurationElement
的ElementInformation
。
// if not the default value...
if (MyConfigurationElement.ElementInformation.Properties["example"].ValueOrigin!=
PropertyValueOrigin.Default)
{
...
}
还请参阅PropertyValueOrigin枚举值的文档。
https://stackoverflow.com/questions/29799341
复制