Permalink
Fetching contributors…
Cannot retrieve contributors at this time
132 lines (93 sloc) 11.6 KB
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
dotnet-clr
article
reflection, generic types
generics [.NET Framework], reflection
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

  1. Get an instance of xref:System.Type that represents the generic type. In the following code, the type is obtained using the C# typeof operator (GetType in Visual Basic, typeid in 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 named t.

    [!code-cppHowToGeneric#2] [!code-csharpHowToGeneric#2] [!code-vbHowToGeneric#2]

  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]

  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]

  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]

  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]

  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]

  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]

  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

  1. 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]

  2. 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]

  3. 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]

  4. 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 Example class in the resulting Dictionary<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# using statements (Imports in 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