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.
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);
...
}
}
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With