Silverlight TypeDescriptor.GetConverter заменяет
Я пытаюсь использовать проект LINQ to CSV в silverlight (его отличный проект), потому что его open source я понял, что могу просто перекомпилировать как библиотеку классов silverlight, но, к сожалению, она использует функцию, недоступную в silverlight. метод TypeDescriptor.GetConverter.
Он использует это, чтобы найти преобразователи типов для правильного анализа столбцов csv соответствующим классам CLR. У меня нет проблем с внесением изменений в источники linqtocsv, чтобы он работал в Silverlight, но я просто не знаю, что эквивалентная операция будет в silverlight. Различные поисковые запросы Google привели меня на страницу , но все, что говорится, состоит в том, что у анализатора XAML есть способ сделать это (но это не так скажем, как получить доступ к этой функции).
В двух словах, вопрос:
как мне реплицировать функциональность TypeDescriptor.GetConverter
?
Мне не обязательно нужно точное падение в замене, я просто хочу знать, как это сделать, без жесткого кодирования группы типов < --- > ассоциаций типов.
Ответы
Ответ 1
На светлых фреймах у вас есть ограниченные возможности; Я бы не уклонился от небольшого жесткого кодирования, особенно если вам нужно только поддерживать основные типы. Он также будет проще и быстрее, чем полный параметр TypeConverter
. Что-то вроде:
static object Parse(Type type, string s)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Boolean: return bool.Parse(s);
case TypeCode.Byte: return byte.Parse(s);
case TypeCode.Char: return s[0];
case TypeCode.DateTime: return DateTime.Parse(s);
...
}
}
Ответ 2
Я разработал довольно полный набор инструментов для решения этой проблемы. Есть много шагов, но вот оно:
1) Возвращает исходное значение, если целевой тип Assignable из исходного значения
2) Постройте преобразователь типа в противном случае (сюда входят интересные части)
public static TypeConverter GetTypeConverter(Type type)
{
TypeConverterAttribute attribute = (TypeConverterAttribute)Attribute.GetCustomAttribute(type, typeof(TypeConverterAttribute), false);
if (attribute != null)
{
try
{
var converterType = Type.GetType(attribute.ConverterTypeName, false);
if (converterType != null)
{
return (Activator.CreateInstance(converterType) as TypeConverter);
}
}
catch {}
}
return new XamlStringConverter(type);
}
Ничего удивительного здесь. Но обратите внимание, что XamlStringConverter возвращается, если конвертер не найден. Он использует Xaml Parser для преобразования вещей. Поле типа включено в конвертер и содержит тип, переданный конструктору.
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
var strValue = value as string;
if (strValue != null) {
if (this.type == typeof(bool)) {
return bool.Parse(strValue);
}
if (this.type.IsEnum) {
return Enum.Parse(this.type, stringValue, false);
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("<ContentControl xmlns='http://schemas.microsoft.com/client/2007' xmlns:c='" + ("clr-namespace:" + this.type.Namespace + ";assembly=" + this.type.Assembly.FullName.Split(new char[] { ',' })[0]) + "'>\n");
stringBuilder.Append("<c:" + this.type.Name + ">\n");
stringBuilder.Append(strValue);
stringBuilder.Append("</c:" + this.type.Name + ">\n");
stringBuilder.Append("</ContentControl>");
ContentControl instance = XamlReader.Load(stringBuilder.ToString()) as ContentControl;
if (instance != null) {
return instance.Content;
}
}
return base.ConvertFrom(context, culture, value);
}
Ответ 3
Если вы уверены, что можете полагаться на согласованность, используйте это:
private static object DeserializeValue(string value, Type type)
{
//uncomment if used with XML
//value = HttpUtility.HtmlDecode(value);
switch (Type.GetTypeCode(type))
{
case TypeCode.Empty:
return null;
case TypeCode.DBNull:
return DBNull.Value;
case TypeCode.Object:
throw new InvalidCastException(
string.Format("The type '{0}' is not supported.", type));
case TypeCode.String:
return value;
default:
{
var convertible = value as IConvertible;
return convertible.ToType(type, CultureInfo.InvariantCulture);
}
}
}
Убедитесь, что ваша функция сериализации является той же культурой, что и десериализация для согласованности:
private static string SerializeValue(object value)
{
if (!(value is IConvertible))
throw new InvalidCastException(
string.Format("The type '{0}' is not supported.", value.GetType()));
var convertible = (IConvertible)value;
var str = convertible.ToString(CultureInfo.InvariantCulture);
//uncomment if you're serializing to XML
//return HttpUtility.HtmlEncode(str);
return str;
}
Обратите внимание, что поддерживаются только примитивные типы.
Ответ 4
От: http://lostechies.com/jimmybogard/2010/02/19/automapper-for-silverlight-3-0-alpha/
private static TypeConverter GetTypeConverter(Type type)
{
var attributes = type.GetCustomAttributes(typeof(TypeConverterAttribute), false);
if (attributes.Length != 1)
return new TypeConverter();
var converterAttribute = (TypeConverterAttribute)attributes[0];
var converterType = Type.GetType(converterAttribute.ConverterTypeName);
if (converterType == null)
return new TypeConverter();
return Activator.CreateInstance(converterType) as TypeConverter;
}