Generic Class & Type.GetType()

11,821

Solution 1

Something like this:

Type typeArgument = Type.GetType("Type From DB as String", true, true);
Type template = typeof(MyClass<>);
Type genericType = template.MakeGenericType(typeArgument);
object instance = Activator.CreateInstance(genericType);

Now you won't be able to use that as a MyClass<T> in terms of calling methods on it, because you don't know the T... but you could define a non-generic base class or interface with some methods in which don't require T, and cast to that. Or you could call the methods on it via reflection.

Solution 2

Generics in reflection are a bit more complex than this. What you're looking for are the GetGenericTypeDefinition() and MakeGenericType() methods. Take your generic type (you can get it by calling GetType() on an instance, or using typeof(MyClass<Object>)), and call GetGenericTypeDefinition() to get the basic, open generic type (MyClass<T>). Then, on that type, call MakeGenericType() and pass it an array with one element; the type you want to use to close the generic. That will get you a generic type closed with your dynamically discovered type (MyClass<MyType>), which you can pass to Activator.CreateInstance().

Share:
11,821
Andy
Author by

Andy

Updated on September 14, 2022

Comments

  • Andy
    Andy over 1 year

    Bit of a puzzler, I have a generic class

    public abstract class MyClass<T> : UserControl
    {
    
    }
    

    and I have got a type like this

    Type type = Type.GetType("Type From DB as String", true, true);
    

    and I want to create and instance of MyClass using the type... But this doesn't work.

    MyClass<type> control = (MyClass<type>)LoadControl("/UsercControl.ascx");
    

    Any ideas????

  • Anthony Pegram
    Anthony Pegram over 13 years
    I was going to post similar code, but I'm unsure how you would use the result. Are you constrained to reflection? (Ah, you added more text confirming my thoughts.)
  • KeithS
    KeithS over 13 years
    You can certainly use that as a MyClass<T>, because you DO know the T. Look at the name of the type and you'll see it's a mashup of the generic class name and the parameter types. However, I do not think that the typeof(MyClass<>) is legal; you have to specify a type closure, then strip it out using GetGenericTypeDefinition)
  • Anthony Pegram
    Anthony Pegram over 13 years
    @KeighS, Jon's code (typeof(MyClass<>)) certainly works. Test it for yourself.
  • Jon Skeet
    Jon Skeet over 13 years
    @KeithS: You don't know it at compile time, so you can't declare a variable of that type or cast instance to that type. However, typeof(MyClass<>) definitely is legal.
  • P Daddy
    P Daddy over 13 years
    You've got a typo in line 3. It should be template.MakeGenericType.
  • Andy
    Andy over 13 years
    Could I do this with a UserControl that is loaded in? as above?
  • Andy
    Andy over 13 years
    I am really close now, thanks guys. Now I just need to work out how to do this with UserControls, I wouldn't use UserControls, but it is being loaded from a DB along with the Type....
  • Jon Skeet
    Jon Skeet over 13 years
    @P Daddy: Fixed, thanks. @Andy: It should work, so long as there's a parameterless constructor - and so long as the very first line works. What's going wrong at the moment?
  • Andy
    Andy over 13 years
    I have gone with the quick and dirty way... Switch statement only ever going to be 5 possible datatypes (int, string, float, bool and datetime)
  • Danial Delkhosh
    Danial Delkhosh over 3 years
    Generic types are resolved at compile time and could not be resolved using reflection