How To: Make dynamic generic types
Some time ago, I started wondering: “How could I create specific generic objects such as List or Dictionary with types sent as parameters?”. We all know that between “” we must provide the type(s), but we cannot certainly do something like “Dictionary”.
My dear workmate Angel “Java” Lopez told me once that such dynamic creation of generics could be done (not in that way, he meant that the objective could be reached
). So, I started searching and asking, till I found the method Type.MakeGenericType(Type[] args). I read the documentation and finally got the idea to work! So I’ll share this with you!
Sample Code
This example shows a GenericsFactory class that populates generic objects according to the types passed as parameters. For this purpose, the class exposes a CreateGenericInstance(Type baseType, Type[] typeArguments) method.
Parameters:
- baseType: a type that will be the generic base type, and
- typeArguments: an array of arguments which will provide the types for the generic arguments.
Returns:
- object.
public class GenericsFactory
{
public object CreateGenericInstance(
Type baseType, Type[] typeArguments
)
{
return Activator.CreateInstance(baseType.MakeGenericType(
typeArguments));
}
}
This class receives the generic base class type and its generics arguments, and then it calls the MakeGenericType(Type[] args) method of the System.Type class for the baseType which constructs the Generic.
Now, we can set our Client class (here’s a Windows Console Application) to use the GenericsFactory class as follows:
class Program
{
static void Main(string[] args)
{
GenericsFactory myGenericsFactory = new GenericsFactory();
Type[] myTypeArguments = { typeof(string), typeof(object) };
Dictionary<string, object> myDictionary =
(Dictionary<string, object>)myGenericsFactory.CreateGenericInstance(
typeof(Dictionary), myTypeArguments);
Console.WriteLine(myDictionary.GetType().FullName);
Console.Read();
}
}
Here, I’m creating a new Dictionary. If you have a look at the Client code, I’m sending the base type object representing the generic Dictionary type omitting the type arguments, but keeping the comma that separates them, so that the compiler can infer the number of type parameters (and, of course, to avoid exceptions
). Then, I also send an array of types (string for TKey and object for TValue) to replace the type parameters of Dictionary.
NOTE: Casting is needed as the CreateGenericInstance() method returns object!
Finally, I call the MakeGenericType(Type[] args) method on the baseType which will return the type for Dictionary. Activator.CreateInstance(Type TType) just populates the object that will be returned according to the type.
The Console.WriteLine() line displays in the console the built type of the new object.
More information:
- Type.MakeGenericType Method.
- Type Class and Type Members.
- Reflection and Generic Types.
- Generics in the .NET Framework.
- Cheers, Nacho
Ver este tópico en español.