Freigeben über


TypeBuilder.GetField Method (Type, FieldInfo)

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Returns the field of the specified constructed generic type that corresponds to the specified field of the generic type definition.

Namespace:  System.Reflection.Emit
Assembly:  mscorlib (in mscorlib.dll)

Syntax

'Declaration
Public Shared Function GetField ( _
    type As Type, _
    field As FieldInfo _
) As FieldInfo
public static FieldInfo GetField(
    Type type,
    FieldInfo field
)

Parameters

  • type
    Type: System.Type
    The constructed generic type whose field is returned.
  • field
    Type: System.Reflection.FieldInfo
    A field on the generic type definition of type, which specifies which field of type to return.

Return Value

Type: System.Reflection.FieldInfo
The field of type corresponding to field, which specifies a field belonging to the generic type definition of type.

Exceptions

Exception Condition
ArgumentException

type does not represent a generic type.

-or-

type is not of type TypeBuilder.

-or-

The declaring type of field is not a generic type definition.

-or-

The declaring type of field is not the generic type definition of type.

Remarks

The GetField method provides a way to get a FieldInfo object that represents a field of a constructed generic type whose generic type definition is represented by a TypeBuilder object.

For example, suppose you have a TypeBuilder object that represents the type G<T> in C# syntax (G(Of T) in Visual Basic, generic <T> ref class G in C++) and a FieldBuilder object that represents a field public T F in C# syntax (Public F As T in Visual Basic, public: T F in C++) that is defined by G<T>. Suppose that G<T> has a generic method with type parameter U that creates an instance of the constructed type G<U> and calls field F on that instance. In order to emit the function call, you need a FieldInfo object that represents F on the constructed type — in other words, that is of type U rather than type T. To do this, first call the MakeGenericType method on the TypeBuilder object, specifying the GenericTypeParameterBuilder object that represents U as the type argument. Then call the GetField method with the return value of the MakeGenericType method as parameter type and the FieldBuilder object that represents F as parameter field. The return value is the FieldInfo object you need to emit the function call. The code example demonstrates this scenario.

Examples

The following example demonstrates the use of the static (Shared in Visual Basic) GetField method.

The example contains source code for a generic class named Sample that has a type parameter T. The class has a field named Field, of type T, and a generic method GM with its own type parameter, U. Method GM creates an instance of Sample, substituting its own type parameter U for the type parameter of Sample, and stores its input parameter in Field.

The code in class Example demonstrates the use of the SetSignature method in emitting generic code. The Main method of class Example creates a dynamic assembly containing a class named Sample, and uses the TypeBuilder.DefineGenericParameters method to make it generic by adding a type parameter named T. A default constructor and a field named Field, of type T, are added to class Sample. A method GM is added, and turned into a generic method using the DefineGenericParameters method. The type parameter of GM is named U. After the type parameter is defined, the signature of GM is added, using the SetSignature method. There is no return type, and no required or custom modifiers, so all the parameters of this method are nulla null reference (Nothing in Visual Basic) except parameterTypes, which sets the type of the only parameter of the method; this is set to the method's type parameter, U. The body of the method creates an instance of the constructed type Sample<U> (Sample(Of U) in Visual Basic), assigns the method's parameter to Field, and then returns the new instance of the constructed type.

The example creates the generic type Sample, and then creates the constructed type Sample<int> (Sample(Of Integer) in Visual Basic). From the constructed type, the static generic method GM<string> (Shared generic method GM(Of String) in Visual Basic) is created and invoked to create an instance of Sample<string>.

Imports System.Reflection
Imports System.Reflection.Emit

' Compiling this class produces MSIL similar to that generated by
' the Reflection.Emit code in class Example.
'
Public Class Sample(Of T)

   Public Data As T

   ' GM is a Shared method that doesn't use T. It's a factory 
   ' method that creates an instance of Sample, substituting U, the
   ' type parameter of GM, for T. GM then assigns the argument you
   ' pass it to the public Data field of Sample, and returns the
   ' new instance of Sample.
   Public Shared Function GM(Of U)(ByVal val As U) As Sample(Of U)

      Dim s As New Sample(Of U)
      s.Data = val
      Return s

   End Function
End Class


Public Class Example

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

      ' This code does the same thing as the late-bound code at
      ' the end of the Demo method. It calls the shared method GM,
      ' using a constructed type. Any type can be substituted for T
      ' when you construct this sample; it doesn't have to be the type
      ' you're going to specify for U. This is because GM is a Shared
      ' method, and U is independent of T.
      Dim sampleOfString As Sample(Of String) = _
                  Sample(Of Integer).GM(Of String)("This is my data.")

      ' Display the value of the Data field:
      outputBlock.Text &= _
         "The value of the Data field: '" & sampleOfString.Data & "'" & vbLf & vbLf    


      Dim myDomain As AppDomain = AppDomain.CurrentDomain
      Dim myAsmName As New AssemblyName("TypeBuilderGetFieldExample")
      Dim myAssembly As AssemblyBuilder = _
          myDomain.DefineDynamicAssembly(myAsmName, _
              AssemblyBuilderAccess.Run)
      Dim myModule As ModuleBuilder = _
          myAssembly.DefineDynamicModule(myAsmName.Name)

      ' Define the sample type.
      Dim myType As TypeBuilder = myModule.DefineType( _
          "Sample", _
          TypeAttributes.Class Or TypeAttributes.Public)

      ' Add a type parameter, making the type generic.
      Dim typeParamNames() As String = {"T"}
      Dim typeParams As GenericTypeParameterBuilder() = _
          myType.DefineGenericParameters(typeParamNames)

      ' Define the default constructor. Usually it is not necessary
      ' to define the default constructor explicitly, but to instantiate
      ' Sample(Of U) you have to have its constructor, and in order to 
      ' get that constructor you need to pass the constructor of 
      ' Sample(Of T) to the Shared GetConstructor method. The only way
      ' to get a reference to the constructor of Sample(Of T) is to use
      ' the DefineDefaultConstructor method.
      Dim ctor As ConstructorBuilder = _
          myType.DefineDefaultConstructor( _
              MethodAttributes.PrivateScope Or MethodAttributes.Public _
              Or MethodAttributes.HideBySig Or MethodAttributes.SpecialName _
              Or MethodAttributes.RTSpecialName)

      ' Add a field of type T, with the name Data.
      Dim fieldData As FieldBuilder = myType.DefineField( _
          "Data", typeParams(0), FieldAttributes.Public)

      ' Add a method and make it generic, with a type parameter named 
      ' U. Note how similar this is to the way Sample is turned into 
      ' a generic type. The method has no signature, because the type of
      ' its only parameter is U, which is not yet defined.
      Dim genMethod As MethodBuilder = _
          myType.DefineMethod("GM", _
              MethodAttributes.Public Or MethodAttributes.Static)
      Dim methodParams As GenericTypeParameterBuilder() = _
          genMethod.DefineGenericParameters(New String() {"U"})
      Dim typeParameterU As GenericTypeParameterBuilder = methodParams(0)

      ' Construct the type Sample(Of U), which is referred to as a 
      ' constructed type, by using MakeGenericType.
      Dim tSampleOfU As Type = myType.MakeGenericType(typeParameterU)

      ' Now add a signature for genMethod, specifying U as the type of
      ' the method's only parameter. The return type is Sample(Of U),
      ' and there are no custom modifiers.
      genMethod.SetSignature(tSampleOfU, Nothing, Nothing, _
          New Type() { typeParameterU }, Nothing, Nothing)

      ' Emit a method body for the generic method.
      Dim ilg As ILGenerator = genMethod.GetILGenerator()

      ' Create a local variable to store the instance of
      ' Sample(Of U). This is variable 0 (Ldloc_0, Stloc_0).
      ilg.DeclareLocal(tSampleOfU)


      ' To instantiate the constructed type Sample(Of U), you have to 
      ' have its constructor. To get that constructor, pass the
      ' constructor of the generic type definition, Sample(Of T), to 
      ' the Shared TypeBuilder.GetConstructor method. 
      '
      Dim ctorOfU As ConstructorInfo = _
          TypeBuilder.GetConstructor(tSampleOfU, ctor)

      ' Create an instance of Sample(Of U), and store it in the local 
      ' variable.
      ilg.Emit(OpCodes.Newobj, ctorOfU)
      ilg.Emit(OpCodes.Stloc_0)


      ' In order to store the value in the field of the new instance 
      ' of Sample(Of U), you need a FieldInfo that represents the 
      ' Data field of the constructed type. Use TypeBuilder.GetField to 
      ' obtain this FieldInfo.
      Dim fieldDataOfU As FieldInfo = _
          TypeBuilder.GetField(tSampleOfU, fieldData)

      ' To store the value in the instance field, load the Sample(Of U)
      ' instance, then load the parameter of genMethod, then call
      ' Stfld.
      ilg.Emit(OpCodes.Ldloc_0)
      ilg.Emit(OpCodes.Ldarg_0)
      ilg.Emit(OpCodes.Stfld, fieldDataOfU)

      ' Load the instance of Sample(Of U) and return it.
      ilg.Emit(OpCodes.Ldloc_0)
      ilg.Emit(OpCodes.Ret)


      ' Create type Sample(Of T).
      Dim completed As Type = myType.CreateType()

      ' In order to call the Shared method GM, you need a constructed
      ' type. You cannot call GM by using the generic type definition.
      ' Therefore, create a constructed type. It doesn't matter what
      ' type you use for the type parameter. Integer is used here.
      Dim constructed As Type = completed.MakeGenericType(GetType(Integer))

      ' Get a generic method definition for Shared generic method GM.
      ' This generic method definition is specific to Sample(Of Integer),
      ' but that doesn't matter because GM doesn't depend on the type
      ' argument of Sample.
      Dim gm As MethodInfo = constructed.GetMethod("GM", _
                              BindingFlags.Public Or BindingFlags.Static)

      ' Construct GM(Of String) and display its reflected signature.
      Dim gmConstructed As MethodInfo = gm.MakeGenericMethod(GetType(String))
      outputBlock.Text &= _
         "The constructed generic method: " & gmConstructed.ToString() & vbLf

      ' Finally, invoke the constructed method to create an instance of 
      ' Sample(Of String), and then display the contents of the Data 
      ' field of the new instance. 
      Dim obj As Object = _
         gmConstructed.Invoke(Nothing, New Object() {"This is my data."})
      outputBlock.Text &= _
         "The value of the Data field: '" & _
            obj.GetType().InvokeMember("Data", _
                                       BindingFlags.GetField, _
                                       Type.DefaultBinder, _
                                       obj, _
                                       Nothing) & "'" & vbLf
   End Sub
End Class

' This example produces the following output:
'
'The value of the Data field: 'This is my data.'
'
'The constructed generic method: Sample[System.String] GM[String](System.String)
'The value of the Data field: 'This is my data.'
using System;
using System.Reflection;
using System.Reflection.Emit;

// Compiling this class produces MSIL similar to that generated by
// the Reflection.Emit code in class Example.
//
public class Sample<T>
{
   public T Data;

   // GM is a Shared method that doesn't use T. It's a factory 
   // method that creates an instance of Sample, substituting U, the
   // type parameter of GM, for T. GM then assigns the argument you
   // pass it to the public Data field of Sample, and returns the
   // new instance of Sample.
   public static Sample<U> GM<U>(U val)
   {
      Sample<U> s = new Sample<U>();
      s.Data = val;
      return s;
   }
}

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      // This code does the same thing as the late-bound code at
      // the end of the Demo method. It calls the shared method GM,
      // using a constructed type. Any type can be substituted for T
      // when you construct this sample; it doesn't have to be the type
      // you're going to specify for U. This is because GM is a Shared
      // method, and U is independent of T.
      Sample<string> sampleOfString = Sample<int>.GM<string>("This is my data.");

      // Display the value of the Data field:
      outputBlock.Text += 
         "The value of the Data field: '" + sampleOfString.Data + "'\n\n";


      AppDomain myDomain = AppDomain.CurrentDomain;
      AssemblyName myAsmName = new AssemblyName("TypeBuilderGetFieldExample");
      AssemblyBuilder myAssembly = 
         myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);
      ModuleBuilder myModule = myAssembly.DefineDynamicModule(myAsmName.Name);

      // Define the sample type.
      TypeBuilder myType = myModule.DefineType("Sample", 
                                TypeAttributes.Class | TypeAttributes.Public);

      // Add a type parameter, making the type generic.
      string[] typeParamNames = {"T"};
      GenericTypeParameterBuilder[] typeParams = 
                                 myType.DefineGenericParameters(typeParamNames);

      // Define the default constructor. Usually it is not necessary
      // to define the default constructor explicitly, but to instantiate
      // Sample(Of U) you have to have its constructor, and in order to 
      // get that constructor you need to pass the constructor of 
      // Sample(Of T) to the Shared GetConstructor method. The only way
      // to get a reference to the constructor of Sample(Of T) is to use
      // the DefineDefaultConstructor method.
      ConstructorBuilder ctor = 
         myType.DefineDefaultConstructor(MethodAttributes.PrivateScope | 
                  MethodAttributes.Public | MethodAttributes.HideBySig | 
                  MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

      // Add a field of type T, with the name Data.
      FieldBuilder fieldData = 
         myType.DefineField("Data", typeParams[0], FieldAttributes.Public);

      // Add a method and make it generic, with a type parameter named 
      // U. Note how similar this is to the way Sample is turned into 
      // a generic type. The method has no signature, because the type of
      // its only parameter is U, which is not yet defined.
      MethodBuilder genMethod = myType.DefineMethod("GM", 
                           MethodAttributes.Public | MethodAttributes.Static);
      GenericTypeParameterBuilder[] methodParams = 
                           genMethod.DefineGenericParameters(new string[] {"U"});
      GenericTypeParameterBuilder typeParameterU = methodParams[0];

      // Construct the type Sample(Of U), which is referred to as a 
      // constructed type, by using MakeGenericType.
      Type tSampleOfU = myType.MakeGenericType(typeParameterU);

      // Now add a signature for genMethod, specifying U as the type of
      // the method's only parameter. The return type is Sample(Of U),
      // and there are no custom modifiers.
      genMethod.SetSignature(tSampleOfU, null, null, 
                             new Type[] { typeParameterU }, null, null);

      // Emit a method body for the generic method.
      ILGenerator ilg = genMethod.GetILGenerator();

      // Create a local variable to store the instance of
      // Sample(Of U). This is variable 0 (Ldloc_0, Stloc_0).
      ilg.DeclareLocal(tSampleOfU);


      // To instantiate the constructed type Sample(Of U), you have to 
      // have its constructor. To get that constructor, pass the
      // constructor of the generic type definition, Sample(Of T), to 
      // the Shared TypeBuilder.GetConstructor method. 
      //
      ConstructorInfo ctorOfU = TypeBuilder.GetConstructor(tSampleOfU, ctor);

      // Create an instance of Sample(Of U), and store it in the local 
      // variable.
      ilg.Emit(OpCodes.Newobj, ctorOfU);
      ilg.Emit(OpCodes.Stloc_0);


      // In order to store the value in the field of the new instance 
      // of Sample(Of U), you need a FieldInfo that represents the 
      // Data field of the constructed type. Use TypeBuilder.GetField to 
      // obtain this FieldInfo.
      FieldInfo fieldDataOfU = TypeBuilder.GetField(tSampleOfU, fieldData);

      // To store the value in the instance field, load the Sample(Of U)
      // instance, then load the parameter of genMethod, then call
      // Stfld.
      ilg.Emit(OpCodes.Ldloc_0);
      ilg.Emit(OpCodes.Ldarg_0);
      ilg.Emit(OpCodes.Stfld, fieldDataOfU);

      // Load the instance of Sample(Of U) and return it.
      ilg.Emit(OpCodes.Ldloc_0);
      ilg.Emit(OpCodes.Ret);


      // Create type Sample(Of T).
      Type completed = myType.CreateType();

      // In order to call the Shared method GM, you need a constructed
      // type. You cannot call GM by using the generic type definition.
      // Therefore, create a constructed type. It doesn't matter what
      // type you use for the type parameter. Integer is used here.
      Type constructed = completed.MakeGenericType(typeof(int));

      // Get a generic method definition for Shared generic method GM.
      // This generic method definition is specific to Sample(Of Integer),
      // but that doesn't matter because GM doesn't depend on the type
      // argument of Sample.
      MethodInfo gm = 
         constructed.GetMethod("GM", BindingFlags.Public | BindingFlags.Static);

      // Construct GM(Of String) and display its reflected signature.
      MethodInfo gmConstructed = gm.MakeGenericMethod(typeof(string));
      outputBlock.Text += 
         "The constructed generic method: " + gmConstructed.ToString() + "\n";

      // Finally, invoke the constructed method to create an instance of 
      // Sample(Of String), and then display the contents of the Data 
      // field of the new instance. 
      object obj = gmConstructed.Invoke(null, new object[] { "This is my data." });
      outputBlock.Text += "The value of the Data field: '" + 
         obj.GetType().InvokeMember("Data", 
                                    BindingFlags.GetField, 
                                    Type.DefaultBinder, 
                                    obj, 
                                    null) + "'\n";
   }
}

/* This example produces the following output:

The value of the Data field: 'This is my data.'

The constructed generic method: Sample[System.String] GM[String](System.String)
The value of the Data field: 'This is my data.'
 */

Version Information

Silverlight

Supported in: 5, 4, 3

Platforms

For a list of the operating systems and browsers that are supported by Silverlight, see Supported Operating Systems and Browsers.