Type Converter to Type

What happens when you need to pass a type as a string? Well, if the string is an assembly qualified type name, and if the assembly is either in Global Assembly Cache or in a known location – such as the Bin folder or a probed path – you’re likely to succeed. But, what if that isn’t the case? Well, we can follow these steps:

  1. Try to locate the type the usual way, by calling Type.GetType;
  2. Look the type in the current executing, entry and calling assemblies;
  3. Look it up in all of the loaded assemblies for the current domain (could be a lot);
  4. Hook up the TypeResolve event of the current app domain (I am not going to show that).

Normally, in .NET we use type converters for doing this kind of stuff in configuration files or ASP.NET markup. Following that, a type converter for turning a string into a type might look like this:

public sealed class TypeTypeConverter : TypeConverter

{

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)

    {

        if (sourceType == typeof (string))

        {

            return true;

        }

 

        return base.CanConvertFrom(context, sourceType);

    }

 

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)

    {

        if (destinationType == typeof (Type))

        {

            return true;

        }

 

        return base.CanConvertTo(context, destinationType);

    }

 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)

    {

        var typeName = value.ToString();

 

        //first attempt

        var type = Type.GetType(typeName, false, true);

 

        if (type == null)

        {

            //second attempt

            var assemblies = new[] { Assembly.GetEntryAssembly(), Assembly.GetCallingAssembly(), Assembly.GetExecutingAssembly() }.Where(asm => asm != null).Distinct();

 

            foreach (var assembly in assemblies)

            {

                type = assembly.GetType(typeName, false, true);

 

                if (type != null)

                {

                    break;

                }

            }

        }

 

        if (type == null)

        {

            //third attempt

            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

 

            foreach (var assembly in assemblies)

            {

                type = assembly.GetType(typeName, false, true);

 

                if (type != null)

                {

                    break;

                }

            }

        }

 

        return type;

    }

 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)

    {

        if (destinationType == typeof (Type))

        {

            return this.ConvertFrom(context, culture, value);

        }

 

        return base.ConvertTo(context, culture, value, destinationType);

    }

}

We just need to apply a TypeConverterAttribute attribute to a property and the magic occurs naturally:

[TypeConverter(typeof(TypeTypeConverter))]

public Type Type { get; set; }

Or if we need to invoke it explicitly:

var converter = TypeDescriptor.GetConverter(typeof(Type));

var type = converter.ConvertFromString("MyNamespace.MyClass");

And that’s it. Keep in mind that it is always preferable that you specify an assembly qualified type name, but if that can’t be done, this might come in handy.

Published by

Ricardo Peres

Team Leader at Dixons Carphone. Microsoft MVP.

Leave a Reply

Your email address will not be published. Required fields are marked *