Ashley Davis
Ashley Davis

Reputation: 10039

How to lookup and invoke a .Net TypeConverter for a particular type?

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 to look up and invoke a TypeConverter for a particular type?

Consider this C# example:

//
// Convert obj to the type specified by 'toType'.
// 
object ConvertTo(object obj, Type toType)
{
    if (TypeIsEqualOrDerivesFrom(obj.GetType(), toType)) <-- I know how to implement this.
    {
        // The type of obj is the same as the type specified by 'toType' or
        // the type of obj derives from the type specified by 'toType'.
        return obj;
    }

    if (TypeConverterExists(obj.GetType(), toType) <-- How do I implement this?
    {
        // There exists a type convertor that is capable of converting from 
        // the type of obj to the type specified by 'toType'.
        return InvokeTypeConverter(obj, toType); <-- How do I implement this?
    }

    throw new TypeConversionFailedException();
}

Upvotes: 10

Views: 13899

Answers (4)

Thomas Levesque
Thomas Levesque

Reputation: 292755

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...

Upvotes: 2

Jeff Moser
Jeff Moser

Reputation: 20053

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.

Upvotes: 1

Steve Dignan
Steve Dignan

Reputation: 8560

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?).

Upvotes: 10

Marc Gravell
Marc Gravell

Reputation: 1064224

    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)

Upvotes: 38

Related Questions