views:

79

answers:

4

Hi All,

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

A: 

You create new objects using reflection:

type.GetConstructor(new Type[]{}).Invoke(new object[]{});
Grzenio
A: 

You must construct the class via reflection.

See http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx for more details.

darasd
+1  A: 

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

KeithS
+2  A: 

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.

Jon Skeet
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.)
Anthony Pegram
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)
KeithS
@KeighS, Jon's code (`typeof(MyClass<>)`) certainly works. Test it for yourself.
Anthony Pegram
@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.
Jon Skeet
You've got a typo in line 3. It should be `template.MakeGenericType`.
P Daddy
Could I do this with a UserControl that is loaded in? as above?
Andy
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....
Andy
@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?
Jon Skeet
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)
Andy