我有一处用DefaultValueAttribute
装饰的房产。
代码如下:
[DefaultValue(typeof(Encoding), "utf-8")]
public Encoding Encoding { get; set; }
有一种重置方法可以恢复所有属性的所有默认值:
public void Reset()
{
foreach (var property in TypeDescriptor.GetProperties(typeof(ILoggedChannelValueFileExportInfo)).Cast<PropertyDescriptor>())
{
property.ResetValue(this);
}
}
这非常适用于所有标准属性,包括ReturnType为CultureInfo
的属性。我尝试用大写指定utf-8
、utf8
和两者,但都不起作用。
我必须指定什么才能使其工作?
我可以通过反射来做到这一点,但我希望有一种方法可以使用TypeDescriptor
。
编辑:由于Hans Passant的回答,我写了一篇TypeConverter
。这就是整个代码:
public class Foo
{
[TypeConverter(typeof(EncodingTypeConverter))]
[DefaultValue(typeof(Encoding), "UTF-8")]
public Encoding Encoding { get; set; }
public void Reset()
{
foreach (var property in TypeDescriptor.GetProperties(this).Cast<PropertyDescriptor>())
{
property.ResetValue(this);
}
}
}
public class EncodingTypeConverter : 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 value is string ? Encoding.GetEncoding((string)value) : base.ConvertFrom(context, culture, value);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return destinationType == typeof(string) ? value.ToString() : base.ConvertTo(context, culture, value, destinationType);
}
}
在创建实例并调用Reset
之后,Encoding仍然为null,并且不会从EncodingTypeConverter
调用任何方法。我该怎么办?"
不涉及UI,也不涉及属性网格。唯一应该重置该值的TypeDescriptor。
编辑:几乎不可能编写自己的TypeConverter
调用,因为DefaultValueAttribute
不存储指定的字符串值。很疼。我的实现不起作用。也许有人可以用它来创建一个解决方案:
public virtual void ResetValues()
{
foreach (var property in TypeDescriptor.GetProperties(typeof(TAttributedType)).Cast<PropertyDescriptor>())
{
if (property.CanResetValue(this))
{
property.ResetValue(this);
continue;
}
var defaultValueAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];
var typeConverterAttribute = (TypeConverterAttribute)property.Attributes[typeof(TypeConverterAttribute)];
if (defaultValueAttribute == null || !(defaultValueAttribute.Value is string) ||
typeConverterAttribute == null || string.IsNullOrWhiteSpace(typeConverterAttribute.ConverterTypeName))
{
continue;
}
var typeConverterType = Type.GetType(typeConverterAttribute.ConverterTypeName);
if (typeConverterType == null)
{
continue;
}
var typeConverter = (TypeConverter)Activator.CreateInstance(typeConverterType);
if (typeConverter.CanConvertFrom(typeof(string)))
{
var propertyValue = typeConverter.ConvertFrom(defaultValueAttribute.Value);
if (propertyValue != null)
{
property.SetValue(this, propertyValue);
}
}
}
}
添加TypeConverterAttribute
和定义DefaultValue(typeof(Encoding), "UTF-8")
将不起作用。DefaultValue
的构造函数试图从不使用TypeConverterAttribute
的TypeDescriptor
中找到一个TypeConverter
。
这里是ResetValues
-方法的一个实现,该方法使用DefaultValueAttribute
和TypeConverterAttribute
中的字符串值来加载默认值。
public virtual void ResetValues()
{
foreach (var property in TypeDescriptor.GetProperties(typeof(TAttributedType)).Cast<PropertyDescriptor>())
{
var defaultValueAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];
var typeConverterAttribute = (TypeConverterAttribute)property.Attributes[typeof(TypeConverterAttribute)];
if (defaultValueAttribute != null && defaultValueAttribute.Value is string &&
typeConverterAttribute != null && !string.IsNullOrWhiteSpace(typeConverterAttribute.ConverterTypeName))
{
var typeConverterType = Type.GetType(typeConverterAttribute.ConverterTypeName);
if (typeConverterType != null)
{
var typeConverter = (TypeConverter)Activator.CreateInstance(typeConverterType);
if (typeConverter.CanConvertFrom(typeof(string)))
{
var propertyValue = typeConverter.ConvertFrom(defaultValueAttribute.Value);
if (propertyValue != null)
{
property.SetValue(this, propertyValue);
continue;
}
}
}
}
if (property.CanResetValue(this))
{
property.ResetValue(this);
}
}
}
使用的TypeConverter
是:
public class EncodingTypeConverter : 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 value is string ? Encoding.GetEncoding((string)value) : base.ConvertFrom(context, culture, value);
}
}
其属性为:
[TypeConverter(typeof(EncodingTypeConverter))]
[DefaultValue("UTF-8")]
public Encoding Encoding { get; set; }
注意,ResetValues
-方法首先测试TypeConverter
和指定的DefaultValue
。这是必需的,因为如果字符串被指定为默认值,PropertyDescriptor.CanResetValue()
将返回true
。这无法转换为编码。