DefaultValueAttriubte如何用于编码



我有一处用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-8utf8和两者,但都不起作用。

我必须指定什么才能使其工作?

我可以通过反射来做到这一点,但我希望有一种方法可以使用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的构造函数试图从不使用TypeConverterAttributeTypeDescriptor中找到一个TypeConverter

这里是ResetValues-方法的一个实现,该方法使用DefaultValueAttributeTypeConverterAttribute中的字符串值来加载默认值。

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。这无法转换为编码。

相关内容

  • 没有找到相关文章

最新更新