Instantiating Generic Types at runtime

The Activator class is of good use when you want to instantiate classes at runtime. Here’s a sample of how this works.

            Type t = Type.GetType(“CompanyNameSpace.MyClass”);

            Object o = Activator.CreateInstance(t);

Looks pretty easy. It gets a bit more interesting when you want to instantiate a generic type at runtime. First, we need to find out the fullname that is used for the generic type. If you don’t know the string representation of a type,  you can create a small project using the type and then look at the type-properties in the debugger. As a sample, I’m using the following class:

    public class CustomerInfo

    {

        private string m_name;

 

        public string Name

        {

            get { return m_name; }

            set { m_name = value; }

        }

 

        private string m_city;

 

        public string City

        {

            get { return m_city; }

            set { m_city = value; }

        }

 

        public CustomerInfo(string name, string city)

        {

            m_name = name;

            m_city = city;

        }

    }

Let’s use the Generic List type with this custom class, like this:

            List<CustomerInfo> list1 = new List<CustomerInfo>();

If you run the code and set a break point right after the the instantiation of list1, you can see the string representation of the list1’s type:

“System.Collections.Generic.List`1[DemoGenerics.CustomerInfo]”

You see that the string contains  `1 and the type the List-object can contain. The 1 after the backtick (`) indicates the number of type parameters for the generic type. `1 means that the generic type has one parameter.

So, to get a Type object for this Generic type, we can use:

Type listType = Type.GetType(“System.Collections.Generic.List`1[DemoGenerics.CustomerInfo]”);

The next challenge is to instantiate the type and use the object in our code. We don’t know the type of object at runtime, so we might use Object, but that’s pretty awkward:

object o = Activator.CreateInstance(listType);

Since Object has limited capabilities, the compiler defaults to these limitations and we cannot do anything besides what Object can do. If we can assume that the type implements the generic IList<> interface, the compiler allows for us to use the methods and properties available in IList<>. Second, we can try to instantiate the generics class like this:

IList<object> list2 = (IList<object>)Activator.CreateInstance(listType);

At runtime, however, this will result in an InvalidCastException. This is obvious since object !=  CustomerInfo. A way to resolve this, is to specify an interface as the type parameter. This could be an empty interface, like:

    interface ICustomObject

    {

    }

We could then say that the custom class implements this interface:

public class CustomerInfo : ICustomObject

And by doing so, we can instantiate the Generics list, with a custom class, ehrr interface, parameter like this:

            Type listType = Type.GetType(“System.Collections.Generic.List`1[DemoGenerics.ICustomObject]”);

            IList<ICustomObject> list2 = (List<ICustomObject>)Activator.CreateInstance(listType);

 

            list2.Add(new CustomerInfo(“Charles”, “New York”));

            list2.Add(new CustomerInfo(“Zlatan”, “Sofia”));

            list2.Add(new CustomerInfo(“Sujesh”, “Bangalore”));     

There you go.

Happy coding.