陈斌彬的技术博客

Stay foolish,stay hungry

TypeConverter的使用

我们知道,C#中有int.Parse,int.TryParse这样神奇的功能,那它们又是如何做到的呢?我们试着自己也来自定义一个“转换器”。

首先,定义一个类:

public class Human
{
    public string Name { get; set; }

    public Human Child { get; set; }
}

这个类具有两个属性:

  • string类型的Name

  • Human类型的Child

现在,我期望为Human实例的Child属性赋一个Human类型的值,并且Child.Name就是这个字符串的值。

我们先在Button1_Click事件中尝试着这样写:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Human h = (Human)this.FindResource("human");
        MessageBox.Show(h.Child.Name);
    }

运行后报错,告诉Child不存在,为什么Child不存在呢?原因很简单,Human实例的Child属性是Human类型,而“ABC”是一个字符串,编译器不知道如何将一个字符串实例转换成一个Human实例。那我们应该怎么做呢?办法是使用TypeConverter和TypeConvertAttribute这两个类。

首先,我们要从TypeConverter中派生出自己的类,并重写它的一个ConvertFrom方法。这个方法有一个参数名为value,我们要做的就是讲这个值“翻译”成合适的值赋给对象的属性:

using System.ComponentModel;

public class StringToHumanTypeConverter : TypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            Human h = new Human();
            h.Name = value as string;
            return h;
        }

        return base.ConvertFrom(context, culture, value);
    }
}

有了这个类还不够,还要使用TypeConverterAttribute这个特征类把StringToHumanTypeConverter这个类“粘贴”到作为目标的Human类上。

[TypeConverterAttribute(typeof(StringToHumanTypeConverter))]
public class Human
{
    public string Name { get; set; }

    public Human Child { get; set; }
}

因为特征类在使用的时候可以省略Attribute这个词,所以也可以写成:

[TypeConverter(typeof(StringToHumanTypeConverter))]
public class Human
{
    public string Name { get; set; }

    public Human Child { get; set; }
}

但这样写,我们需要认清写在方括号里的是TypeConverterAttribute而不是TypeConverter。

完成之后,再单击按钮,想要的结果就弹出来了。

Resource Reference