Link to home
Start Free TrialLog in
Avatar of bemara57
bemara57

asked on

How do I create an instance with generic types with Activator.CreateInstance?

I have a class that has a generic type and I'm trying to create an instance using the activator but having trouble with it. This is what I have:

    public abstract class MyBaseClass<T> where T : new()
    {
          ...
          public abstract T DoSomething();
    }

    public class MyClass<T> : MyBaseClass<T> where T : new()
    {
         ...
          public override T DoSomething() { .. }        
    }

And this is what I'm trying to do:
MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance(Type.GetType("MyClass"));

But this gives my a null error: System.ArgumentNullException: Value cannot be null. How do I tell the Activator.CreateInstance to give <Customer> to "MyClass" which I'm trying to instantiate??




Avatar of JasonRawlins
JasonRawlins
Flag of United States of America image

Try this instead
MyBaseClass<Customer> customerProvider =
(MyClass<Customer>)Activator.CreateInstance(typeof(MyClass<Customer>));

Open in new window

Avatar of bemara57
bemara57

ASKER

Thanks but that kind of defeats the purpose of what I'm trying to do. I'm passing in a string that represents the class I'm trying to instantiate like this:

string someStr = "MyClass";
MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance(Type.GetType(someStr));

I tried putting 'string someStr = "MyClass<Customer>"' but that breaks my XML file where the string is originally stored, plus I'd want to pass <Customer>, <Order>, <Item> and so on in different methods so I wouldn't want to hard code the generic type either. I also tried this but didn't work:

string someStr = "MyClass";
MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance<Customer>(Type.GetType(someStr));

It gave a compiler error about Activator.CreateInstance can't find that overloaded method. Any other ideas on how to pass <Customer> to the Activator? There's gotta be some kind of syntax for it but couldn't find it anywhere.
bemara57,

At the time you want to invoke CreateInstance, you need to know whether you are creating it for a Customer, and Order or an Item. So, you might try something like this:

string className = GoGetMyClassFromXML(); // Or however you get it, just returns MyClass
string currentContent = "Customer";
string genericClass = string.Format("{0}<{1}>", className, currentContent);
MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance(Type.GetType(genericClass ));

Jim
That was a pretty good idea but it still gives me a null exception. I even tried hardcoding everything like this and still gave me a null exception:

MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance("MyClass<Customer>");

And just to make sure I wasn't doing anything stupid somewhere, doing this worked fine:
MyBaseClass<Customer> customerProvider = new MyClass<Customer>();

Any other ideas??
I'll see if I can figure out a way to make it work.

Jim
There is a generic version of CreateInstance you can use. I don't know why you would use Activator.CreateInstance when you already know the type, however. Here is a good article about the difference between the generic and System.Type methods

http://blogs.msdn.com/kcwalina/archive/2005/11/17/GenericMethodVsSystemType.aspx
MyBaseClass<Customer> customerProvider = Activator.CreateInstance<MyClass<Customer>>();

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of JimBrandley
JimBrandley
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I got it! Phew did I have to dig.

It has very weird syntax with a backtick and brackets. Initially I tried following the MSDN guide on GetType (two-thirds down the page: http://msdn2.microsoft.com/en-us/library/w3f99sx1.aspx) which told me to do the following but still came up with a null:
        Type constructedType = Type.GetType("MyClass`1[Customer]");

So in the end, this finally worked for me:
        Type classType = Type.GetType("MyClass`1");
        Type[] typeParams = new Type[] { typeof(Customer) };
        Type constructedType = classType.MakeGenericType(typeParams);

        MyBaseClass<Customer> customerProvider =
            Activator.CreateInstance(constructedType) as MyBaseClass<Customer>;

Thanks again for the help Jim, I didn't realize the null was happening at GetType.. the whole time I thought the problem was with Activator.CreateInstance.