I have a class that takes a Generic Type as part of its initialization.
public class AnimalContext<T>
{
public DoAnimalStuff()
{
//AnimalType Specific Code
}
}
What I can do right now is
AnimalContext<Donkey> donkeyContext = new AnimalContext<Donkey>();
AnimalContext<Orca> orcaContext = new AnimalContext<Orca>();
But what I need/want to do is be able to declare an AnimalContext initialized to a type that is only known at runtime. For instance,
Animal a = MyFavoriteAnimal(); //returns an instance of a class
//implementing an animal
AnimalContext<a.GetType()> a_Context = new AnimalContext<a.GetType()>();
a_Context.DoAnimalStuff();
Is this even possible? I can't seem to find an answer for this online.
What you mean by this part is possible:
new AnimalContext<a.GetType()>();
Obviously that exact syntax is wrong, and we'll get to that, but it is possible to construct an instance of a generic type at runtime when you don't know the type parameters until runtime.
What you mean by this part is not:
AnimalContext<a.GetType()> a_Context
That is, it is impossible to type a variable as a generic type if you don't know the type parameters at compile-time. Generics are compile-time constructs, and rely on having the type information available at compile-time. Given this, you lose all the benefits of generics if you don't know the types at compile-time.
Now, to construct an instance of a generic type at runtime when you don't know the type until runtime, you can say:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
Note that the compile-time type of a_context
is object
. You will have to cast a_context
to a type or interface that defines the methods you need to access. Often what you'll see people do here is have the generic type AnimalContext<T>
implement some interface (say IAnimalContext
) or inherit from a non-generic base class (say AnimalContext
) that defines the methods they need (so then you can cast a_context
to the interface or the non-generic base class). Another alternative is to use dynamic
. But again, keep in mind, you have none of the benefits of generic types in doing this.
You can use reflection with generic type by using MakeGenericType
method and take adavantage of dynamic
keyword:
var type = typeof (AnimalContext<>).MakeGenericType(a.GetType());
dynamic a_Context = Activator.CreateInstance(type);
So you can call:
a_Context.DoAnimalStuff();
Or use reflection again to call method:
type.GetMethod("DoAnimalStuff").Invoke(a_Context, null);
You would need to create the type using Reflection and then invoke that type. Something like:
Animal a = MyFavoriteAnimal();
var contextType = typeof(EsbRepository<>).MakeGenericType(a.GetType());
dynamic context = Activator.CreateInstance(contextType);
context.DoAnimalStuff();
The use of dynamic means that the context variable will be evaluated at run time allowing for you to call the DoAnimalStuff method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With