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