I would like to implement a general purpose runtime type conversion function that makes use .Net TypeConverters to do the conversion.
Does anyone know how to how t
TypeConverter converter = TypeDescriptor.GetConverter(sourceType);
if(converter.CanConvertTo(destinationType)) {
return converter.ConvertTo(obj, destinationType);
}
converter = TypeDescriptor.GetConverter(destinationType);
if(converter.CanConvertFrom(sourceType)) {
return converter.ConvertFrom(obj);
}
You could also look at Convert.ChangeType(obj, destinationType)
I don't know how robust it is, but I sometimes use this code for generic type conversion :
public T ConvertTo<T>(object value)
{
return (T)Convert.ChangeType(value, typeof(T));
}
I don't know if the ChangeType method use TypeConverters...
Here's the code used in one of our existing apps... not sure if it's ideal but it works well for us.
/// <summary>
/// Attempts to convert a value using any customer TypeConverters applied to the member
/// </summary>
/// <param name="value">Object containing the value to be assigned</param>
/// <param name="member">Member to be assigned to</param>
/// <returns><paramref name="value"/> converted to the appropriate type</returns>
public static Object CustomTypeConversion ( object value, MemberInfo member )
{
if ( value == null || value == DBNull.Value )
return value;
if ( member == null )
throw new ArgumentNullException ( );
List<TypeConverter> converters = GetCustomTypeConverters ( member );
foreach ( TypeConverter c in converters )
{
if ( c.CanConvertFrom ( value.GetType ( ) ) )
return c.ConvertFrom ( value );
}
if ( member is PropertyInfo )
{
PropertyInfo prop = member as PropertyInfo;
return ConvertToNative( value , prop.PropertyType );
}
return ConvertToNative ( value, member.MemberType.GetType ( ) );
}
/// <summary>
/// Extracts and instantiates any customer type converters assigned to a
/// derivitive of the <see cref="System.Reflection.MemberInfo"/> property
/// </summary>
/// <param name="member">Any class deriving from MemberInfo</param>
/// <returns>A list of customer type converters, empty if none found</returns>
public static List<TypeConverter> GetCustomTypeConverters ( System.Reflection.MemberInfo member )
{
List<TypeConverter> result = new List<TypeConverter>();
try
{
foreach ( TypeConverterAttribute a in member.GetCustomAttributes( typeof( TypeConverterAttribute ) , true ) )
{
TypeConverter converter = Activator.CreateInstance( Type.GetType( a.ConverterTypeName ) ) as TypeConverter;
if ( converter != null )
result.Add( converter );
}
}
catch
{
// Let it go, there were no custom converters
}
return result;
}
/// <summary>
/// Attempts to cast the incoming database field to the property type
/// </summary>
/// <param name="value">Database value to cast</param>
/// <param name="castTo">Type to cast to</param>
/// <returns>The converted value, if conversion failed the original value will be returned</returns>
public static object ConvertToNative ( object value , Type castTo )
{
try
{
return Convert.ChangeType( value , castTo , System.Threading.Thread.CurrentThread.CurrentCulture );
}
catch
{
return value;
}
}
Just call the CustomTypeConversion method and away you go... probably a little more than you need but being thorough isn't a crime (or is it?).
In addition to Marc's answer, you might consider that ASP.NET's ViewState does a similar function to what you're asking to do. It tries to find the most efficient conversion.
It might be worth a look at this page and possibly this one too.