Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

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 Type object that represents the generic type. The principal difference is that a generic type has a list of Type objects that represent its generic type parameters. The first procedure in this topic examines generic types.

You can create a 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 Type that represents the generic type. In the following code, the type is obtained by using the C# typeof operator (GetType in Visual Basic, typeid in Visual C++). See the Type class topic for other ways to get a Type object. Note that in the rest of this procedure, the type is contained in a method parameter named t.

    
    Dim d1 As Type = GetType(Dictionary(Of ,))
    
    
    
  2. Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition.

    
    output.Text &= "   Is this a generic type? " _ 
        & t.IsGenericType & vbCrLf
    output.Text &= "   Is this a generic type definition? " _ 
        & t.IsGenericTypeDefinition & vbCrLf
    
    
    
  3. Get an array that contains the generic type arguments, using the GetGenericArguments method.

    
    Dim typeParameters() As Type = t.GetGenericArguments()
    
    
    
  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 IsGenericParameter property.

    
    output.Text &= String.Format("   List {0} type arguments:" & vbCrLf, _
        typeParameters.Length)
    For Each tParam As Type In typeParameters
        If tParam.IsGenericParameter Then
            DisplayGenericParameter(tParam)
        Else
            output.Text &= String.Format("      Type argument: {0}" & vbCrLf, _
                tParam)
        End If
    Next
    
    
    
  5. In the type system, a generic type parameter is represented by an instance of Type, just as ordinary types are. The following code displays the name and parameter position of a 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.

    
    Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
        output.Text &= String.Format("      Type parameter: {0} position {1}" & vbCrLf, _
            tp.Name, tp.GenericParameterPosition)
    
    
    
  6. Determine the base type constraint and the interface constraints of a generic type parameter by using the GetGenericParameterConstraints method to obtain all the constraints in a single array. Constraints are not guaranteed to be in any particular order.

    
    Dim classConstraint As Type = Nothing
    
    For Each iConstraint As Type In tp.GetGenericParameterConstraints()
        If iConstraint.IsInterface Then
            output.Text &= String.Format("         Interface constraint: {0}" & vbCrLf, _
                iConstraint)
        End If
    Next
    
    If classConstraint IsNot Nothing Then
        output.Text &= String.Format("         Base type constraint: {0}" & vbCrLf, _
            tp.BaseType)
    Else
        output.Text &= "         Base type constraint: None" & vbCrLf
    End If
    
    
    
  7. Use the GenericParameterAttributes 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.

    
    Dim sConstraints As GenericParameterAttributes = _
        tp.GenericParameterAttributes And _
        GenericParameterAttributes.SpecialConstraintMask
    
    
    
  8. The special constraint attributes are flags, and the same flag (GenericParameterAttributes.None) 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 GenericParameterAttributes.SpecialConstraintMask to isolate the special constraint flags.

    
    If sConstraints = GenericParameterAttributes.None Then
        output.Text &= "         No special constraints." & vbCrLf
    Else
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.DefaultConstructorConstraint) Then
            output.Text &= "         Must have a parameterless constructor." & vbCrLf
        End If
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.ReferenceTypeConstraint) Then
            output.Text &= "         Must be a reference type." & vbCrLf
        End If
        If GenericParameterAttributes.None <> (sConstraints And _
            GenericParameterAttributes.NotNullableValueTypeConstraint) Then
            output.Text &= "         Must be a non-nullable value type." & vbCrLf
        End If
    End If
    
    
    

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 MakeGenericType method.

To construct an instance of a generic type

  1. Get a Type object that represents the generic type. The following code gets the generic type Dictionary(Of TKey, TValue) in two different ways: by using the Type.GetType(String) method overload with a string describing the type, and by calling the GetGenericTypeDefinition method on the constructed type Dictionary<String, Example> (Dictionary(Of String, Example) in Visual Basic). The MakeGenericType method requires a generic type definition.

    
    ' Use the GetType operator to create the generic type 
    ' definition directly. To specify the generic type definition,
    ' omit the type arguments but retain the comma that separates
    ' them.
    Dim d1 As Type = GetType(Dictionary(Of ,))
    
    ' You can also obtain the generic type definition from a
    ' constructed class. In this case, the constructed class
    ' is a dictionary of Example objects, with String keys.
    Dim d2 As New Dictionary(Of String, Example)
    ' Get a Type object that represents the constructed type,
    ' and from that get the generic type definition. The 
    ' variables d1 and d4 contain the same type.
    Dim d3 As Type = d2.GetType()
    Dim d4 As Type = d3.GetGenericTypeDefinition()
    
    
    
  2. Construct an array of type arguments to substitute for the type parameters. The array must contain the correct number of 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 String, and the values in the dictionary are instances of a class named Example.

    
    Dim typeArgs() As Type = _
        { GetType(String), GetType(Example) }
    
    
    
  3. Call the MakeGenericType method to bind the type arguments to the type parameters and construct the type.

    
    Dim constructed As Type = _
        d1.MakeGenericType(typeArgs)
    
    
    
  4. Use the CreateInstance(Type) 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.

    
    Dim o As Object = Activator.CreateInstance(constructed)
    
    
    

The following code example defines a DisplayGenericType method to examine the generic type definitions and constructed types that are used in the code and to display their information. The DisplayGenericType method shows how to use the IsGenericType, IsGenericParameter, and GenericParameterPosition properties and the GetGenericArguments 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 Dictionary(Of TKey, TValue) class by creating an array of type arguments and calling the MakeGenericType method. The program compares the Type object that was constructed using MakeGenericType to a Type object that was obtained using typeof (GetType in Visual Basic), demonstrating that they are the same. Similarly, the program uses the GetGenericTypeDefinition method to obtain the generic type definition of the constructed type, and compares it to the Type object representing the Dictionary(Of TKey, TValue) class.


Imports System
Imports System.Reflection
Imports System.Collections.Generic

' Define an example interface.
Public Interface ITestArgument
End Interface

' Define an example base class.
Public Class TestBase
End Class

' Define a generic class with one parameter. The parameter
' has three constraints: It must inherit TestBase, it must
' implement ITestArgument, and it must have a parameterless
' constructor.
Public Class Test(Of T As {TestBase, ITestArgument, New})
End Class

' Define a class that meets the constraints on the type
' parameter of class Test.
Public Class TestArgument
    Inherits TestBase
    Implements ITestArgument
    Public Sub New()
    End Sub
End Class

Public Class Example

    ' Makes the TextBlock available to all methods in Example.
    Private Shared output As System.Windows.Controls.TextBlock

    ' The following method displays information about a generic
    ' type.
    Private Shared Sub DisplayGenericType(ByVal t As Type)
        output.Text &= vbCrLf & t.ToString() & vbCrLf
        output.Text &= "   Is this a generic type? " _ 
            & t.IsGenericType & vbCrLf
        output.Text &= "   Is this a generic type definition? " _ 
            & t.IsGenericTypeDefinition & vbCrLf

        ' Get the generic type parameters or type arguments.
        Dim typeParameters() As Type = t.GetGenericArguments()

        output.Text &= String.Format("   List {0} type arguments:" & vbCrLf, _
            typeParameters.Length)
        For Each tParam As Type In typeParameters
            If tParam.IsGenericParameter Then
                DisplayGenericParameter(tParam)
            Else
                output.Text &= String.Format("      Type argument: {0}" & vbCrLf, _
                    tParam)
            End If
        Next
    End Sub

    ' The following method displays information about a generic
    ' type parameter. Generic type parameters are represented by
    ' instances of System.Type, just like ordinary types.
    Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
        output.Text &= String.Format("      Type parameter: {0} position {1}" & vbCrLf, _
            tp.Name, tp.GenericParameterPosition)

        Dim classConstraint As Type = Nothing

        For Each iConstraint As Type In tp.GetGenericParameterConstraints()
            If iConstraint.IsInterface Then
                output.Text &= String.Format("         Interface constraint: {0}" & vbCrLf, _
                    iConstraint)
            End If
        Next

        If classConstraint IsNot Nothing Then
            output.Text &= String.Format("         Base type constraint: {0}" & vbCrLf, _
                tp.BaseType)
        Else
            output.Text &= "         Base type constraint: None" & vbCrLf
        End If

        Dim sConstraints As GenericParameterAttributes = _
            tp.GenericParameterAttributes And _
            GenericParameterAttributes.SpecialConstraintMask
        If sConstraints = GenericParameterAttributes.None Then
            output.Text &= "         No special constraints." & vbCrLf
        Else
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.DefaultConstructorConstraint) Then
                output.Text &= "         Must have a parameterless constructor." & vbCrLf
            End If
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.ReferenceTypeConstraint) Then
                output.Text &= "         Must be a reference type." & vbCrLf
            End If
            If GenericParameterAttributes.None <> (sConstraints And _
                GenericParameterAttributes.NotNullableValueTypeConstraint) Then
                output.Text &= "         Must be a non-nullable value type." & vbCrLf
            End If
        End If
    End Sub

    Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)

        ' Makes the TextBlock available to all methods in Example.
        output = outputBlock

        ' Two ways to get a Type object that represents the generic
        ' type definition of the Dictionary class. 
        '
        ' Use the GetType operator to create the generic type 
        ' definition directly. To specify the generic type definition,
        ' omit the type arguments but retain the comma that separates
        ' them.
        Dim d1 As Type = GetType(Dictionary(Of ,))

        ' You can also obtain the generic type definition from a
        ' constructed class. In this case, the constructed class
        ' is a dictionary of Example objects, with String keys.
        Dim d2 As New Dictionary(Of String, Example)
        ' Get a Type object that represents the constructed type,
        ' and from that get the generic type definition. The 
        ' variables d1 and d4 contain the same type.
        Dim d3 As Type = d2.GetType()
        Dim d4 As Type = d3.GetGenericTypeDefinition()

        ' Display information for the generic type definition, and
        ' for the constructed type Dictionary(Of String, Example).
        DisplayGenericType(d1)
        DisplayGenericType(d2.GetType())

        ' Construct an array of type arguments to substitute for 
        ' the type parameters of the generic Dictionary class.
        ' The array must contain the correct number of types, in 
        ' the same order that they appear in the type parameter 
        ' list of Dictionary. The key (first type parameter)
        ' is of type string, and the type to be contained in the
        ' dictionary is Example.
        Dim typeArgs() As Type = _
            { GetType(String), GetType(Example) }

        ' Construct the type Dictionary(Of String, Example).
        Dim constructed As Type = _
            d1.MakeGenericType(typeArgs)

        DisplayGenericType(constructed)

        Dim o As Object = Activator.CreateInstance(constructed)

        output.Text &= vbCrLf & _
            "Compare types obtained by different methods:" & vbCrLf
        output.Text &= "   Are the constructed types equal? " _
            & (d2.GetType() Is constructed) & vbCrLf
        output.Text &= "   Are the generic definitions equal? " _ 
            & (d1 Is constructed.GetGenericTypeDefinition()) & vbCrLf

        ' Demonstrate the DisplayGenericType and 
        ' DisplayGenericParameter methods with the Test class 
        ' defined above. This shows base, interface, and special
        ' constraints.
        DisplayGenericType(GetType(Test(Of )))
    End Sub
End Class

' This example produces output similar to the following:
'
'System.Collections.Generic.Dictionary`2[TKey,TValue]
'   Is this a generic type? True
'   Is this a generic type definition? True
'   List 2 type arguments:
'      Type parameter: TKey position 0
'         Base type constraint: None
'         No special constraints.
'      Type parameter: TValue position 1
'         Base type constraint: None
'         No special constraints.
'
'System.Collections.Generic.Dictionary`2[System.String,SilverlightApplication.Example]
'   Is this a generic type? True
'   Is this a generic type definition? False
'   List 2 type arguments:
'      Type argument: System.String
'      Type argument: SilverlightApplication.Example
'
'System.Collections.Generic.Dictionary`2[System.String,SilverlightApplication.Example]
'   Is this a generic type? True
'   Is this a generic type definition? False
'   List 2 type arguments:
'      Type argument: System.String
'      Type argument: SilverlightApplication.Example
'
'Compare types obtained by different methods:
'   Are the constructed types equal? True
'   Are the generic definitions equal? True
'
'Test`1[T]
'   Is this a generic type? True
'   Is this a generic type definition? True
'   List 1 type arguments:
'      Type parameter: T position 0
'         Interface constraint: SilverlightApplication.ITestArgument
'         Base type constraint: None
'         Must have a parameterless constructor.


  • The code contains the C# using statements (Imports in Visual Basic) that are necessary for compilation.

  • No additional assembly references are required.

  • The code contains a static (Shared in Visual Basic) Demo method that has one parameter, a TextBlock that is used to display the output. For instructions on building the code as part of a simple Silverlight-based application, see Building Examples That Use a Demo Method and a TextBlock Control. You can put all the code in this example into one source file.

Community Additions

ADD
Show:
© 2015 Microsoft