Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

silverlight TypeDescriptor.GetConverter substitute

I am trying to use the LINQ to CSV project in silverlight (its a great project), because its open sourced i figured i could just recompile as a silverlight class library but unfortunately it appears to use a feature not available in silverlight. The TypeDescriptor.GetConverter method.

It uses this to find type converters to properly parse the csv columns to their corresponding CLR types. I have no problem making changes to the linqtocsv sources to make it work in Silverlight, but i just don't know what an equivalent operation would be in silverlight. Various google searches have brought me to this page, but all that says is that the XAML parser has a way of doing this (but it doesn't say how to access this functionality).

In a nutshell, the question is:

how do i replicate the functionality of TypeDescriptor.GetConverter?

I don't necessarily need an exact drop in replacement, i just want to know a good way to do this without hardcoding a bunch of type <---> typeconverter associations.

like image 646
luke Avatar asked Jun 03 '10 01:06

luke


2 Answers

On the light frameworks you have limited options; I wouldn't shy away from a little hard-coding, especially if you only need to support the core types. It will also be simpler and faster than the full TypeConverter option. Something like:

    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);
                ...
        }
    }
like image 58
Marc Gravell Avatar answered Oct 19 '22 20:10

Marc Gravell


I have built a rather comprehensive toolset to solve this issue. There are many steps involved but here it is:

1) Return the original value if the target type is Assignable from the original value 2) Construct a type converter otherwise (here come the interesting parts)

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

Nothing marvellous here. But notice the XamlStringConverter returned if no converter was found. It makes use of the Xaml Parser to convert things. The type field is included in the Converter, and contains the type passed to the 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);
    }
like image 1
Eilistraee Avatar answered Oct 19 '22 21:10

Eilistraee