MethodBuilder.SetSignature Method

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

Sets the method signature, including the return type, the parameter types, and the required and optional custom modifiers of the return type and parameter types.

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

Syntax

'Declaration
Public Sub SetSignature ( _
    returnType As Type, _
    returnTypeRequiredCustomModifiers As Type(), _
    returnTypeOptionalCustomModifiers As Type(), _
    parameterTypes As Type(), _
    parameterTypeRequiredCustomModifiers As Type()(), _
    parameterTypeOptionalCustomModifiers As Type()() _
)
public void SetSignature(
    Type returnType,
    Type[] returnTypeRequiredCustomModifiers,
    Type[] returnTypeOptionalCustomModifiers,
    Type[] parameterTypes,
    Type[][] parameterTypeRequiredCustomModifiers,
    Type[][] parameterTypeOptionalCustomModifiers
)

Parameters

  • returnType
    Type: System.Type
    The return type of the method.
  • returnTypeRequiredCustomModifiers
    Type: array<System.Type[]
    An array of types representing the required custom modifiers, such as IsConst, for the return type of the method. If the return type has no required custom modifiers, specify nulla null reference (Nothing in Visual Basic).
  • returnTypeOptionalCustomModifiers
    Type: array<System.Type[]
    An array of types representing the optional custom modifiers, such as IsConst, for the return type of the method. If the return type has no optional custom modifiers, specify nulla null reference (Nothing in Visual Basic).
  • parameterTypes
    Type: array<System.Type[]
    The types of the parameters of the method.
  • parameterTypeRequiredCustomModifiers
    Type: array<array<System.Type[][]
    An array of arrays of types. Each array of types represents the required custom modifiers for the corresponding parameter, such as IsConst. If a particular parameter has no required custom modifiers, specify nulla null reference (Nothing in Visual Basic) instead of an array of types. If none of the parameters have required custom modifiers, specify nulla null reference (Nothing in Visual Basic) instead of an array of arrays.
  • parameterTypeOptionalCustomModifiers
    Type: array<array<System.Type[][]
    An array of arrays of types. Each array of types represents the optional custom modifiers for the corresponding parameter, such as IsConst. If a particular parameter has no optional custom modifiers, specify nulla null reference (Nothing in Visual Basic) instead of an array of types. If none of the parameters have optional custom modifiers, specify nulla null reference (Nothing in Visual Basic) instead of an array of arrays.

Exceptions

Exception Condition
InvalidOperationException

The current method is generic, but is not a generic method definition. That is, the IsGenericMethod property is true, but the IsGenericMethodDefinition property is false.

Remarks

If the return type and the number and types of the parameters are known when the method is defined, they can be established using any overload of the TypeBuilder.DefineMethod method that accepts an array of parameter types. However, a generic method can have parameters whose types are specified by one or more of its own generic type parameters, which cannot be defined until after the method has been defined. Use this method to set the parameter types in that case.

If neither the return type nor the parameter types have optional or required custom modifiers, such as IsConst, you can use the SetReturnType and SetParameters methods.

Calling this method replaces the parameters and return type established using the TypeBuilder.DefineMethod method.

Examples

The following example shows the use of the SetSignature 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.