4

例如,我想序列化和反序列化一个System.Version对象作为我的应用程序自定义配置部分的一部分。我正在尝试使用以下属性声明来做到这一点:

public class ConfigElement : ConfigurationElement
{
    [ConfigurationProperty("ver", IsRequired = false, DefaultValue = "1.2.4.8")]
    public Version Ver
    {
        get { return (Version)this["ver"]; }
        set { this["ver"] = value; }
    }
}

不幸的是,尝试序列化或使用此属性(带或不带DefaultValue)会产生以下异常消息。

System.Configuration.ConfigurationErrorsException :属性“ver”的值无法转换为字符串。错误是:找不到支持“Version”类型的属性“ver”的字符串转换的转换器。

System.Version.ToString()将对象写入 可使用的众所周知的字符串格式System.Version.ctor(string),因此对于这种类型存在“转换器”似乎是可行的。相比之下,该System.TimeSpan类型具有相似的方法和功能(Parsein-place of .ctor(string)),并且该类型与配置系统配合良好(转换器必须已经存在)。

我怎么知道一个类型是否有合适的转换器?这种类型必须满足什么契约(隐式或其他)?

4

1 回答 1

4

为了使 ConfigurationProperty 起作用,使用的类型必须与TypeConverter相关联,而不是知道如何从字符串转换。ConfigurationProperty 确实有一个Converter属性,但可惜它是只读的。而且,这真的很糟糕,Version 也没有声明隐式 TypeConverter。

不过,您可以做的是以编程方式将TypeConverterAttribute添加到 Version 类,它将解决所有这些问题。因此,在访问配置之前,您基本上需要在程序中调用此行一次:

TypeDescriptor.AddAttributes(typeof(Version), new TypeConverterAttribute(typeof(VersionTypeConverter)));
// ... you can call configuration code now...

使用以下定制的 VersionTypeConverter:

public class VersionTypeConverter : TypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        return new Version((string)value);
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;

        return base.CanConvertFrom(context, sourceType);
    }
}
于 2012-08-16T07:55:49.590 回答