Cannot create a TypeConverter for a generic type

安稳与你 提交于 2019-12-03 10:52:58

I solved this by creating an single Converter that could hanlde all of the types derrived from my generic class. The big issue of knowing the generic arg T within the ConvertFrom was solved by capturing the information in the constructor as seen below.

public MyGenericConverter(Type type)
{
    if (type.IsGenericType 
        && type.GetGenericTypeDefinition() == typeof(MyGenericClass<>)
        && type.GetGenericArguments().Length == 1)
    {
        _genericInstanceType = type;
        _innerType = type.GetGenericArguments()[0];
        _innerTypeConverter = TypeDescriptor.GetConverter(_innerType);            
    }
    else
    {
        throw new ArgumentException("Incompatible type", "type");
    }
}

It took me ages to discover that the .NET infrastructure reflectively calls this constructor overload if it is defined. It was not part of the documented TypeConverter class.

Hope this all helps the next guy.

Although @tcarvin's answer is very interesting - it works for me in .NET Framework 4.6.1 and from what I see in the code it should also work on .NET Core, there is an alternative solution using TypeDescriptionProviderAttribute that doesn't depend on that implementation detail he describes (constructor accepting parameter of type Type).

Having:

public class FooTypeConverter<T> : TypeConverter { ... }

public class FooTypeDescriptor : CustomTypeDescriptor
{
    private Type objectType;

    public FooTypeDescriptor(Type objectType)
    {
        this.objectType = objectType;
    }

    public override TypeConverter GetConverter()
    {
        var genericArg = objectType.GenericTypeArguments[0];
        var converterType = typeof(FooTypeConverter<>).MakeGenericType(genericArg);
        return (TypeConverter)Activator.CreateInstance(converterType);
    }
}

public class FooTypeDescriptionProvider : TypeDescriptionProvider
{
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new FooTypeDescriptor(objectType);
    }
}

you just need to apply TypeDescriptionProviderAttribute to the target class like:

[TypeDescriptionProvider(typeof(FooTypeDescriptionProvider))]
public class Foo<T> { }

and then

TypeDescriptor.GetConverter(typeof(Foo)) will work as intended.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!