2010-06-03 13 views
11

Estoy tratando de usar el proyecto LINQ to CSV en silverlight (es un gran proyecto), porque es de código abierto, pensé que podría simplemente recompilar como una biblioteca de clase Silverlight pero desafortunadamente parece usar una característica no disponible en Silverlight. El método TypeDescriptor.GetConverter.silverlight TypeDescriptor.GetConverter substitute

Utiliza esto para encontrar convertidores de tipos para analizar adecuadamente las columnas csv a sus correspondientes tipos CLR. No tengo problemas para realizar cambios en las fuentes de linqtocsv para que funcionen en Silverlight, pero simplemente no sé cuál sería una operación equivalente en Silverlight. Varias búsquedas en Google me han llevado a este page, pero todo lo que dice es que el analizador XAML tiene una forma de hacerlo (pero no dice cómo acceder a esta funcionalidad).

En pocas palabras, la pregunta es:

¿Cómo puedo replicar la funcionalidad de TypeDescriptor.GetConverter?

No necesito necesariamente una caída exacta en el reemplazo, solo quiero saber una buena forma de hacerlo sin tener que codificar un montón de tipo < ---> asociaciones de tipoconvertidor.

Respuesta

8

En los marcos ligeros tiene opciones limitadas; No rehuiré un poco de hard-coding, especialmente si solo necesitas soportar los tipos principales. También será más simple y más rápido que la opción completa TypeConverter. Algo como:

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); 
       ... 
     } 
    } 
+0

Gracias, esperaba no tener que llegar a esto, pero yo supongo que no es tan grande de un acuerdo ... – luke

1

He creado un conjunto de herramientas bastante completo para resolver este problema. Hay muchos pasos involucrados pero aquí es:

1) devuelven el valor original si el tipo de destino es asignable del valor original 2) Construir un convertidor de tipos de otro modo (aquí vienen las partes interesantes)

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

Nada maravilloso aquí. Pero observe que XamlStringConverter regresó si no se encontró un convertidor. Utiliza el Xaml Parser para convertir cosas. El campo tipo se incluye en el convertidor y contiene el tipo pasado al constructor.

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); 
    } 
+0

que parece una gran solución, excepto [doesn' t trabajo] (http://rextester.com/runcode) en absoluto. Mi objetivo es únicamente el método 'TypeDescriptor.GetConverter' para ser utilizado en tipos primitivos. – Shimmy

+0

No te di el código de trabajo: son solo algunos fragmentos. Por ejemplo, la clase XamlStringConverter no está definida. ¿Debo actualizarlo con el código de clase completo?Realmente no es tan complicado: cree una clase XamlStringConverter, un constructor con un parámetro Type y un campo de tipo poblado por el constructor. Eso es todo. (Y compruebe que no cometí un error tipográfico) – Eilistraee

+0

No necesito el XamlStringConverter, solo quiero una salida de cadena deserializada. De todos modos, utilicé [la solución de abajo] (http://stackoverflow.com/a/9370752/75500), preferí la solución TypeConverter porque me pareció más segura, pero [que] (http://stackoverflow.com/a/9370752/75500) la solución parece funcionar muy bien para un impacto de rendimiento considerablemente bajo. – Shimmy

0

Si está seguro de que puede confiar en la consistencia, utilice esto:

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

Asegúrese que su función es la serialización misma cultura que la deserialización de coherencia:

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

Tenga en cuenta que solo los tipos primitivos son compatibles.

0

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