无法为generics类型创建TypeConverter

我想为generics类创建一个TypeConverter ,如下所示:

 [TypeConverter(typeof(WrapperConverter))] public class Wrapper { public T Value { // get & set } // other methods } public class WrapperConverter : TypeConverter { // only support To and From strings public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(string)) { return true; } return base.CanConvertFrom(context, sourceType); } public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof(string)) { return true; } return base.CanConvertTo(context, destinationType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is string) { TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); T inner = converter.ConvertTo(value, destinationType); return new Wrapper(inner); } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(System.String)) { Wrapper wrapper = value as Wrapper(); TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); return converter.ConvertTo(wrapper.Value, destinationType); } return base.ConvertTo(context, culture, value, destinationType); } } 

问题在于你不能在这一行中使用generics,它是不允许的:

 [TypeConverter(typeof(WrapperConverter))] public class Wrapper 

我的下一个方法是尝试定义一个可以处理任何Wrapper实例的单一非generics转换器。 reflection和generics的混合让我难以理解如何实现ConvertToConvertFrom方法。

例如,我的ConvertTo看起来像这样:

 public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(System.String) && value.GetType().IsGenericType) { // 1. How do I enforce that value is a Wrapper instance? Type innerType = value.GetType().GetGenericArguments()[0]; TypeConverter converter = TypeDescriptor.GetConverter(innerType); // 2. How do I get to the T Value property? Introduce an interface that Wrapper implements maybe? object innerValue = ??? return converter.ConvertTo(innerValue, destinationType); } return base.ConvertTo(context, culture, value, destinationType); } 

ConvertFrom我遇到了最大的问题,因为我无法知道哪个Wrapper类将转换字符串转换为。

我已经创建了几个用于ASP.NET 4 Web API框架的自定义类型和TypeConverters,这也是我需要使用它的地方。

我尝试的另一件事是在运行时分配我的转换器的通用版本,如此处所示,但WebAPI框架不尊重它(意思是,从未创建过转换器)。

最后一点,我使用的是.NET 4.0和VS 2010。

我通过创建一个可以处理从我的generics类中获得的所有类型的转换器来解决这个问题。 通过捕获构造函数中的信息解决了在ConvertFrom中了解genericsarg T的重大问题,如下所示。

 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"); } } 

我花了很长时间才发现.NET基础结构在定义时reflection性地调用此构造函数重载。 它不是记录的TypeConverter类的一部分。

希望这一切都有助于下一个人。