Мне нужен TypeConverter, который в идеале преобразует String в класс перечислимых типов (CountryIso) без необходимости писать конвертер для каждого перечисляемого типа.
Пока мне удалось заставить работать следующее:
CountryIso cI = (CountryIso) "1";
Я просто не могу заставить его работать с генериками! Следующий пример не работает, но почему?
TypeDescriptor.AddProvider(new ExplicitCastDescriptionProvider<CountryIso>(), typeof(CountryIso));
var descriptor = TypeDescriptor.GetConverter(typeof(CountryIso));
var result = descriptor.ConvertFrom("1");
В настоящее время у меня есть общая реализация TypeConverter:
public class ExplicitCastConverter<T>: TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
// Always true: the type determines if a cast is available or not
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
String dummy = (String) value;
//CountryIso tst = (CountryIso) value; // Allowed, no problem casting
//CountryIso tst = (CountryIso) dummy; // Allowed, no problem casting
//var dum_001 = (T) ((String) value); // Does not compile
//var dumdum = (T) value; // Invalid case exception
//var hoot = (T) Convert.ChangeType(value, typeof (T)); // Invalid cast exception
return null;
}
}
Поставщик выглядит следующим образом:
//thanks: http://groups.google.com/group/wpf-disciples/browse_thread/thread/9f7bb40b7413fcd
public class ExplicitCastDescriptionProvider<T> : TypeDescriptionProvider //where T:TypeSafeEnum
{
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new ImplicitCastDescription<T>();
}
}
public class ImplicitCastDescription<T>: CustomTypeDescriptor //where T:TypeSafeEnum
{
public override TypeConverter GetConverter()
{
return new ExplicitCastConverter<T>();
}
}
У меня есть реализация безопасного перечисления типа CountryIso (спасибо StackOverflow!):
public sealed class CountryIso: TypeSafeEnum
{
private static readonly Dictionary<int, CountryIso> InstanceDict = new Dictionary<int, CountryIso>();
public static readonly CountryIso NL = new CountryIso(1, "NL", "Netherlands");
public static readonly CountryIso BE = new CountryIso(2, "BE", "Belgium");
private CountryIso(int value, String name, String description): base(value,name,description)
{
InstanceDict.Add(value, this);
}
public static Dictionary<int, CountryIso> Instances
{
get { return new Dictionary<int, CountryIso>(InstanceDict); }
}
public static explicit operator CountryIso(String i)
{
int index;
return Int32.TryParse(i,out index) ? InstanceDict[index] : null;
}
}
Что наследуется от TypeSafeEnum:
public class TypeSafeEnum
{
protected TypeSafeEnum(int value, String name, String description)
{
Name = name;
Value = value;
Description = description;
}
public int Value{ get; private set; }
public String Name { get; private set; }
public String Description { get; private set; }
}