DefaultValueAttribute如何用于编码?

时间:2014-08-28 08:18:46

标签: c# reflection properties

我有一个用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编码仍为空,并且不会从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);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

添加TypeConverterAttribute并定义DefaultValue(typeof(Encoding), "UTF-8")将无效。 DefaultValue的构造函数尝试从不使用TypeConverter的{​​{1}}中找到TypeDescriptor

以下是TypeConverterAttribute - 方法的实现,该方法使用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

attibuted属性是:

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()。这不能转换为编码。

相关问题