Reputation: 653
I have a generic class
GenericClass<T>
for some reason I need to pass the generic type from another type like that:
say I have some classes
from NormalClass1
to NormalClassN
all of them have property say prop1
with different types
I need to do this
var type1 = typeof(NormalClass1).GetProperty("prop1").GetType();
and send type1
to new instance of GenericClass
like that:
var instance = new GenericClass<type1>();
but an error has occurred that says that
Cannot implicitly convert type 'GenericClass<type1>' to 'GenericClass<T>'
how can I pass this type to GenericClass
Upvotes: 1
Views: 2822
Reputation: 699
There are multiple problems with your code. First of all:
var type1 = typeof(NormalClass1).GetProperty("prop1").GetType();
will return the type PropertyInfo, not the type of the property. What you want is:
var type1 = typeof(NormalClass1).GetProperty("prop1").PropertyType;
Second of all you seem to have a conceptual issue with Generics, Types and TypeParameters.
Basically there is a difference between a Type variable (Type x = typeof(NormalClass1<>
) and a generic Type parameter (the T in NormalClass<T>
).
T is not much more than a placeholder for a Type. You can use typeof(T)
to get the actual Type of T
. Using typeof(x)
on the other hand would result in a compulation error since x is a variable and not a Type. You would use x.GetType()
instead.
You cannot create a generic type via a runtime type variable directly. What you can do instead is creating the generic type via reflection.
The following example should illustrate how to do that
var genericTypeParameter = typeof(NormalClass1).GetProperty("prop1").PropertyType;
var genericBaseType = typeof(GenericClass<>);
var genericType = genericBaseType.MakeGenericType(genericTypeParameter);
var instance = Activator.CreateInstance(genericType);
As you can see, var instance would substitute to object instance. That has to be that way, since you can check the type of compile time. Best Practice would probably be to create a non generic base class for you generic class. You can than use the base class type and have at least a small amount of type checking at runtime, even if you have no chance to test the generic type parameter.
This would be what it would look like:
var instance = (GenericClassBase)Activator.CreateInstance(genericType);
Upvotes: 1
Reputation: 490
You can only do it with Reflection:
var generic = typeof (GenericClass<T>).MakeGenericType(type1);
var instance = Activator.CreateInstance(generic);
Upvotes: 1