| title | ms.custom | ms.date | ms.prod | ms.reviewer | ms.suite | ms.technology | ms.tgt_pltfrm | ms.topic | helpviewer_keywords | ms.assetid | caps.latest.revision | author | ms.author | manager | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
How to: Examine and Instantiate Generic Types with Reflection |
03/30/2017 |
.net-framework |
|
article |
|
f93b03b0-1778-43fc-bc6d-35983d210e74 |
16 |
rpetrusha |
ronpet |
wpickett |
How to: Examine and Instantiate Generic Types with Reflection
Information about generic types is obtained in the same way as information about other types: by examining a xref:System.Type object that represents the generic type. The principle difference is that a generic type has a list of xref:System.Type objects representing its generic type parameters. The first procedure in this section examines generic types.
You can create a xref:System.Type object that represents a constructed type by binding type arguments to the type parameters of a generic type definition. The second procedure demonstrates this.
To examine a generic type and its type parameters
-
Get an instance of xref:System.Type that represents the generic type. In the following code, the type is obtained using the C#
typeofoperator (GetTypein Visual Basic,typeidin Visual C++). See the xref:System.Type class topic for other ways to get a xref:System.Type object. Note that in the rest of this procedure, the type is contained in a method parameter namedt.[!code-cppHowToGeneric#2] [!code-csharpHowToGeneric#2] [!code-vbHowToGeneric#2]
-
Use the xref:System.Type.IsGenericType%2A property to determine whether the type is generic, and use the xref:System.Type.IsGenericTypeDefinition%2A property to determine whether the type is a generic type definition.
[!code-cppHowToGeneric#3] [!code-csharpHowToGeneric#3] [!code-vbHowToGeneric#3]
-
Get an array that contains the generic type arguments, using the xref:System.Type.GetGenericArguments%2A method.
[!code-cppHowToGeneric#4] [!code-csharpHowToGeneric#4] [!code-vbHowToGeneric#4]
-
For each type argument, determine whether it is a type parameter (for example, in a generic type definition) or a type that has been specified for a type parameter (for example, in a constructed type), using the xref:System.Type.IsGenericParameter%2A property.
[!code-cppHowToGeneric#5] [!code-csharpHowToGeneric#5] [!code-vbHowToGeneric#5]
-
In the type system, a generic type parameter is represented by an instance of xref:System.Type, just as ordinary types are. The following code displays the name and parameter position of a xref:System.Type object that represents a generic type parameter. The parameter position is trivial information here; it is of more interest when you are examining a type parameter that has been used as a type argument of another generic type.
[!code-cppHowToGeneric#6] [!code-csharpHowToGeneric#6] [!code-vbHowToGeneric#6]
-
Determine the base type constraint and the interface constraints of a generic type parameter by using the xref:System.Type.GetGenericParameterConstraints%2A method to obtain all the constraints in a single array. Constraints are not guaranteed to be in any particular order.
[!code-cppHowToGeneric#7] [!code-csharpHowToGeneric#7] [!code-vbHowToGeneric#7]
-
Use the xref:System.Type.GenericParameterAttributes%2A property to discover the special constraints on a type parameter, such as requiring that it be a reference type. The property also includes values that represent variance, which you can mask off as shown in the following code.
[!code-cppHowToGeneric#8] [!code-csharpHowToGeneric#8] [!code-vbHowToGeneric#8]
-
The special constraint attributes are flags, and the same flag (xref:System.Reflection.GenericParameterAttributes.None?displayProperty=nameWithType) that represents no special constraints also represents no covariance or contravariance. Thus, to test for either of these conditions you must use the appropriate mask. In this case, use xref:System.Reflection.GenericParameterAttributes.SpecialConstraintMask?displayProperty=nameWithType to isolate the special constraint flags.
[!code-cppHowToGeneric#9] [!code-csharpHowToGeneric#9] [!code-vbHowToGeneric#9]
Constructing an Instance of a Generic Type
A generic type is like a template. You cannot create instances of it unless you specify real types for its generic type parameters. To do this at run time, using reflection, requires the xref:System.Type.MakeGenericType%2A method.
To construct an instance of a generic type
-
Get a xref:System.Type object that represents the generic type. The following code gets the generic type xref:System.Collections.Generic.Dictionary%602 in two different ways: by using the xref:System.Type.GetType%28System.String%29?displayProperty=nameWithType method overload with a string describing the type, and by calling the xref:System.Type.GetGenericTypeDefinition%2A method on the constructed type
Dictionary\<String, Example>(Dictionary(Of String, Example)in Visual Basic). The xref:System.Type.MakeGenericType%2A method requires a generic type definition.[!code-cppHowToGeneric#10] [!code-csharpHowToGeneric#10] [!code-vbHowToGeneric#10]
-
Construct an array of type arguments to substitute for the type parameters. The array must contain the correct number of xref:System.Type objects, in the same order as they appear in the type parameter list. In this case, the key (first type parameter) is of type xref:System.String, and the values in the dictionary are instances of a class named
Example.[!code-cppHowToGeneric#11] [!code-csharpHowToGeneric#11] [!code-vbHowToGeneric#11]
-
Call the xref:System.Type.MakeGenericType%2A method to bind the type arguments to the type parameters and construct the type.
[!code-cppHowToGeneric#12] [!code-csharpHowToGeneric#12] [!code-vbHowToGeneric#12]
-
Use the xref:System.Activator.CreateInstance%28System.Type%29 method overload to create an object of the constructed type. The following code stores two instances of the
Exampleclass in the resultingDictionary<String, Example>object.[!code-cppHowToGeneric#13] [!code-csharpHowToGeneric#13] [!code-vbHowToGeneric#13]
Example
The following code example defines a DisplayGenericType method to examine the generic type definitions and constructed types used in the code and display their information. The DisplayGenericType method shows how to use the xref:System.Type.IsGenericType%2A, xref:System.Type.IsGenericParameter%2A, and xref:System.Type.GenericParameterPosition%2A properties and the xref:System.Type.GetGenericArguments%2A method.
The example also defines a DisplayGenericParameter method to examine a generic type parameter and display its constraints.
The code example defines a set of test types, including a generic type that illustrates type parameter constraints, and shows how to display information about these types.
The example constructs a type from the xref:System.Collections.Generic.Dictionary%602 class by creating an array of type arguments and calling the xref:System.Type.MakeGenericType%2A method. The program compares the xref:System.Type object constructed using xref:System.Type.MakeGenericType%2A with a xref:System.Type object obtained using typeof (GetType in Visual Basic), demonstrating that they are the same. Similarly, the program uses the xref:System.Type.GetGenericTypeDefinition%2A method to obtain the generic type definition of the constructed type, and compares it to the xref:System.Type object representing the xref:System.Collections.Generic.Dictionary%602 class.
[!code-cppHowToGeneric#1] [!code-csharpHowToGeneric#1] [!code-vbHowToGeneric#1]
Compiling the Code
-
The code contains the C#
usingstatements (Importsin Visual Basic) necessary for compilation. -
No additional assembly references are required.
-
Compile the code at the command line using csc.exe, vbc.exe, or cl.exe. To compile the code in Visual Studio, place it in a console application project template.
See Also
xref:System.Type
xref:System.Reflection.MethodInfo
Reflection and Generic Types
Viewing Type Information
Generics