Я хотел бы создать TypeConverter
для общего класса, например:
[TypeConverter(typeof(WrapperConverter<T>))]
public class Wrapper<T>
{
public T Value
{
// get & set
}
// other methods
}
public class WrapperConverter<T> : TypeConverter<T>
{
// 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<T>(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<T> wrapper = value as Wrapper<T>();
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
return converter.ConvertTo(wrapper.Value, destinationType);
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
Проблема заключается в том, что у вас не может быть общего в этой строке, она не разрешена:
[TypeConverter(typeof(WrapperConverter<T>))]
public class Wrapper<T>
Мой следующий подход состоял в том, чтобы попытаться определить один, не общий конвертер, который мог бы обрабатывать любые экземпляры Wrapper<T>
. Смешение как рефлексии, так и дженериков меня озадачило, как реализовать оба методы ConvertTo
и ConvertFrom
.
Так, например, мой 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<T> 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<T> implements maybe?
object innerValue = ???
return converter.ConvertTo(innerValue, destinationType);
}
return base.ConvertTo(context, culture, value, destinationType);
}
В ConvertFrom
У меня есть самая большая проблема, потому что у меня нет способа узнать, какой класс Wrapper будет преобразовывать входящие строки в.
Я создал несколько типов custome и TypeConverters для использования с каркасом веб-API ASP.NET 4, и именно там мне нужно это и для использования.
Еще одна вещь, которую я пробовал, заключалась в том, чтобы назначить мою родовую версию конвертера во время выполнения, как показано здесь, но структура WebAPI не уважала его (что означает, что преобразователь никогда не создавался).
Одна последняя заметка: я использую .NET 4.0 и VS 2010.