TypeBuilder.GetMethod(Type, MethodInfo) 方法
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
傳回對應至泛型類型定義指定方法的指定建構泛型類型的方法。
public:
static System::Reflection::MethodInfo ^ GetMethod(Type ^ type, System::Reflection::MethodInfo ^ method);
public static System.Reflection.MethodInfo GetMethod (Type type, System.Reflection.MethodInfo method);
static member GetMethod : Type * System.Reflection.MethodInfo -> System.Reflection.MethodInfo
Public Shared Function GetMethod (type As Type, method As MethodInfo) As MethodInfo
參數
- type
- Type
傳回方法的建構泛型類別。
- method
- MethodInfo
有關 type
的泛型類型定義方法,指定要傳回的 type
方法。
傳回
表示對應 method
(其指定屬於 type
泛型類型定義的方法) 的 type
方法的 MethodInfo 物件。
例外狀況
method
是非泛型方法定義的泛型方法。
-或-
type
不代表泛型類型。
-或-
type
不是 TypeBuilder型別。
-或-
method
的宣告類型不是泛型類型定義。
-或-
method
的宣告類型不是 type
的泛型類型定義。
範例
下列程式代碼範例包含名為 Sample
之泛型類別的原始程式碼,其類型參數為 T
。 類別具有名為 Field
的欄位、類型 T
,以及名為 GM
的泛型方法,其本身的類型參數為 U
。 方法GM
會建立的Sample
實例,將自己的型別參數取代為的Sample
型別參數U
,並將其輸入參數儲存在 Field
中。 此原始碼已編譯,但未使用;您可以使用 Ildasm.exe (IL 反組譯程式) 來檢視它,並將其與 類別 Example
發出的程式代碼進行比較。
類別 Example
中的程式代碼示範如何使用 GetMethod 方法來發出泛型程序代碼。 類別Main
Example
的 方法會建立包含名為 Sample
的類別的動態元件,並使用 DefineGenericParameters 方法,藉由新增名為T
的型別參數來讓它成為泛型。 無參數建構函式和類型 為 Field
的 T
欄位會新增至 類別 Sample
。 方法 GM
會使用 MethodBuilder.DefineGenericParameters 方法加入並轉換成泛型方法。 的型別參數 GM
名為 U
。 定義型別參數之後,會使用 方法新增 的GM
MethodBuilder.SetSignature簽章。 沒有傳回型別,沒有必要或自定義修飾詞,因此此方法的所有參數除外null
parameterTypes
;parameterTypes
請將方法的唯一參數的類型設定為 U
,方法的泛型型別參數。 方法的主體會在 Visual Basic) 中建立建構型 Sample<U>
別 (Sample(Of U)
的實例、將方法的參數指派給 Field
,然後列印 的值 Field
。 已定義虛擬類型,以儲存進入點方法 Main
。 在 的主體Main
中,靜態GM
方法會在 Visual Basic () Sample(Of Integer)
中建構的泛型型Sample<int>
別上叫用,且型String別取代為 U
。 方法GetMethod是用來建立MethodInfo建構泛型型Sample<U>
別之靜態GM
方法的 ,然後MethodInfo.MakeGenericMethod會使用 方法建立MethodInfo可在方法呼叫中發出的 。
執行程式代碼範例時,它會將發出的元件儲存為 TypeBuilderGetFieldExample.exe。 您可以執行 TypeBuilderGetFieldExample.exe,而且您可以使用 Ildasm.exe (IL 反組譯程式) 來比較發出的程式代碼與編譯成程式代碼範例本身之類別的程式代碼 Sample
。
using System;
using System.Reflection;
using System.Reflection.Emit;
// Compare the MSIL in this class to the MSIL
// generated by the Reflection.Emit code in class
// Example.
public class Sample<T>
{
public T Field;
public static void GM<U>(U val)
{
Sample<U> s = new Sample<U>();
s.Field = val;
Console.WriteLine(s.Field);
}
}
public class Example
{
public static void Main()
{
AppDomain myDomain = AppDomain.CurrentDomain;
AssemblyName myAsmName =
new AssemblyName("TypeBuilderGetFieldExample");
AssemblyBuilder myAssembly = myDomain.DefineDynamicAssembly(
myAsmName, AssemblyBuilderAccess.Save);
ModuleBuilder myModule = myAssembly.DefineDynamicModule(
myAsmName.Name,
myAsmName.Name + ".exe");
// 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 a default constructor. Normally it would
// not be necessary to define the default constructor,
// but in this case it is needed for the call to
// TypeBuilder.GetConstructor, which gets the default
// constructor for the generic type constructed from
// Sample<T>, in the generic method GM<U>.
ConstructorBuilder ctor = myType.DefineDefaultConstructor(
MethodAttributes.PrivateScope | MethodAttributes.Public |
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName);
// Add a field of type T, with the name Field.
FieldBuilder myField = myType.DefineField("Field",
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);
string[] methodParamNames = {"U"};
GenericTypeParameterBuilder[] methodParams =
genMethod.DefineGenericParameters(methodParamNames);
// Now add a signature for genMethod, specifying U
// as the type of the parameter. There is no return value
// and no custom modifiers.
genMethod.SetSignature(null, null, null,
new Type[] { methodParams[0] }, null, null);
// Emit a method body for the generic method.
ILGenerator ilg = genMethod.GetILGenerator();
// Construct the type Sample<U> using MakeGenericType.
Type SampleOfU = myType.MakeGenericType( methodParams[0] );
// Create a local variable to store the instance of
// Sample<U>.
ilg.DeclareLocal(SampleOfU);
// Call the default constructor. Note that it is
// necessary to have the default constructor for the
// constructed generic type Sample<U>; use the
// TypeBuilder.GetConstructor method to obtain this
// constructor.
ConstructorInfo ctorOfU = TypeBuilder.GetConstructor(
SampleOfU, ctor);
ilg.Emit(OpCodes.Newobj, ctorOfU);
// Store the instance in the local variable; load it
// again, and load the parameter of genMethod.
ilg.Emit(OpCodes.Stloc_0);
ilg.Emit(OpCodes.Ldloc_0);
ilg.Emit(OpCodes.Ldarg_0);
// In order to store the value in the field of the
// instance of Sample<U>, it is necessary to have
// a FieldInfo representing the field of the
// constructed type. Use TypeBuilder.GetField to
// obtain this FieldInfo.
FieldInfo FieldOfU = TypeBuilder.GetField(
SampleOfU, myField);
// Store the value in the field.
ilg.Emit(OpCodes.Stfld, FieldOfU);
// Load the instance, load the field value, box it
// (specifying the type of the type parameter, U), and
// print it.
ilg.Emit(OpCodes.Ldloc_0);
ilg.Emit(OpCodes.Ldfld, FieldOfU);
ilg.Emit(OpCodes.Box, methodParams[0]);
MethodInfo writeLineObj =
typeof(Console).GetMethod("WriteLine",
new Type[] { typeof(object) });
ilg.EmitCall(OpCodes.Call, writeLineObj, null);
ilg.Emit(OpCodes.Ret);
// Emit an entry point method; this must be in a
// non-generic type.
TypeBuilder dummy = myModule.DefineType("Dummy",
TypeAttributes.Class | TypeAttributes.NotPublic);
MethodBuilder entryPoint = dummy.DefineMethod("Main",
MethodAttributes.Public | MethodAttributes.Static,
null, null);
ilg = entryPoint.GetILGenerator();
// In order to call the static generic method GM, it is
// necessary to create a constructed type from the
// generic type definition for Sample. This can be any
// constructed type; in this case Sample<int> is used.
Type SampleOfInt =
myType.MakeGenericType( typeof(int) );
// Next get a MethodInfo representing the static generic
// method GM on type Sample<int>.
MethodInfo SampleOfIntGM = TypeBuilder.GetMethod(SampleOfInt,
genMethod);
// Next get a MethodInfo for GM<string>, which is the
// instantiation of GM that Main calls.
MethodInfo GMOfString =
SampleOfIntGM.MakeGenericMethod( typeof(string) );
// Finally, emit the call. Push a string onto
// the stack, as the argument for the generic method.
ilg.Emit(OpCodes.Ldstr, "Hello, world!");
ilg.EmitCall(OpCodes.Call, GMOfString, null);
ilg.Emit(OpCodes.Ret);
myType.CreateType();
dummy.CreateType();
myAssembly.SetEntryPoint(entryPoint);
myAssembly.Save(myAsmName.Name + ".exe");
Console.WriteLine(myAsmName.Name + ".exe has been saved.");
}
}
Imports System.Reflection
Imports System.Reflection.Emit
' Compare the MSIL in this class to the MSIL
' generated by the Reflection.Emit code in class
' Example.
Public Class Sample(Of T)
Public Field As T
Public Shared Sub GM(Of U)(ByVal val As U)
Dim s As New Sample(Of U)
s.Field = val
Console.WriteLine(s.Field)
End Sub
End Class
Public Class Example
Public Shared Sub Main()
Dim myDomain As AppDomain = AppDomain.CurrentDomain
Dim myAsmName As New AssemblyName("TypeBuilderGetFieldExample")
Dim myAssembly As AssemblyBuilder = _
myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Save)
Dim myModule As ModuleBuilder = _
myAssembly.DefineDynamicModule(myAsmName.Name, _
myAsmName.Name & ".exe")
' 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 a default constructor. Normally it would
' not be necessary to define the default constructor,
' but in this case it is needed for the call to
' TypeBuilder.GetConstructor, which gets the default
' constructor for the generic type constructed from
' Sample(Of T), in the generic method GM(Of U).
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 Field.
Dim myField As FieldBuilder = myType.DefineField( _
"Field", 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 methodParamNames() As String = { "U" }
Dim methodParams As GenericTypeParameterBuilder() = _
genMethod.DefineGenericParameters(methodParamNames)
' Now add a signature for genMethod, specifying U
' as the type of the parameter. There is no return value
' and no custom modifiers.
genMethod.SetSignature(Nothing, Nothing, Nothing, _
New Type() { methodParams(0) }, Nothing, Nothing)
' Emit a method body for the generic method.
Dim ilg As ILGenerator = genMethod.GetILGenerator()
' Construct the type Sample(Of U) using MakeGenericType.
Dim SampleOfU As Type = _
myType.MakeGenericType(methodParams(0))
' Create a local variable to store the instance of
' Sample(Of U).
ilg.DeclareLocal(SampleOfU)
' Call the default constructor. Note that it is
' necessary to have the default constructor for the
' constructed generic type Sample(Of U); use the
' TypeBuilder.GetConstructor method to obtain this
' constructor.
Dim ctorOfU As ConstructorInfo = _
TypeBuilder.GetConstructor(SampleOfU, ctor)
ilg.Emit(OpCodes.Newobj, ctorOfU)
' Store the instance in the local variable; load it
' again, and load the parameter of genMethod.
ilg.Emit(OpCodes.Stloc_0)
ilg.Emit(OpCodes.Ldloc_0)
ilg.Emit(OpCodes.Ldarg_0)
' In order to store the value in the field of the
' instance of Sample(Of U), it is necessary to have
' a FieldInfo representing the field of the
' constructed type. Use TypeBuilder.GetField to
' obtain this FieldInfo.
Dim FieldOfU As FieldInfo = _
TypeBuilder.GetField(SampleOfU, myField)
' Store the value in the field.
ilg.Emit(OpCodes.Stfld, FieldOfU)
' Load the instance, load the field value, box it
' (specifying the type of the type parameter, U),
' and print it.
ilg.Emit(OpCodes.Ldloc_0)
ilg.Emit(OpCodes.Ldfld, FieldOfU)
ilg.Emit(OpCodes.Box, methodParams(0))
Dim writeLineObj As MethodInfo = _
GetType(Console).GetMethod("WriteLine", _
New Type() {GetType(Object)})
ilg.EmitCall(OpCodes.Call, writeLineObj, Nothing)
ilg.Emit(OpCodes.Ret)
' Emit an entry point method; this must be in a
' non-generic type.
Dim dummy As TypeBuilder = _
myModule.DefineType("Dummy", _
TypeAttributes.Class Or TypeAttributes.NotPublic)
Dim entryPoint As MethodBuilder = _
dummy.DefineMethod("Main", _
MethodAttributes.Public Or MethodAttributes.Static, _
Nothing, Nothing)
ilg = entryPoint.GetILGenerator()
' In order to call the static generic method GM, it is
' necessary to create a constructed type from the
' generic type definition for Sample. This can be ANY
' constructed type; in this case Sample(Of Integer)
' is used.
Dim SampleOfInt As Type = _
myType.MakeGenericType(GetType(Integer))
' Next get a MethodInfo representing the static generic
' method GM on type Sample(Of Integer).
Dim SampleOfIntGM As MethodInfo = _
TypeBuilder.GetMethod(SampleOfInt, genMethod)
' Next get a MethodInfo for GM(Of String), which is the
' instantiation of generic method GM that is called
' by Sub Main.
Dim GMOfString As MethodInfo = _
SampleOfIntGM.MakeGenericMethod(GetType(String))
' Finally, emit the call. Push a string onto
' the stack, as the argument for the generic method.
ilg.Emit(OpCodes.Ldstr, "Hello, world!")
ilg.EmitCall(OpCodes.Call, GMOfString, Nothing)
ilg.Emit(OpCodes.Ret)
myType.CreateType()
dummy.CreateType()
myAssembly.SetEntryPoint(entryPoint)
myAssembly.Save(myAsmName.Name & ".exe")
Console.WriteLine(myAsmName.Name & ".exe has been saved.")
End Sub
End Class
備註
方法 GetMethod 提供方法來取得 MethodInfo 對象,這個物件表示建構泛型型別的方法,其泛型型別定義是由 TypeBuilder 物件表示。
例如,假設您有 一個 TypeBuilder 物件,代表 G<T>
Visual Basic generic <T> ref class G
中 C# 語法 (G(Of T)
、C++) ,以及MethodBuilder代表Visual Basic 中 C# 語法Function M() As T
中 (方法T M()
的物件,T M()
在 C++) 中G<T>
定義。
G<T>
假設具有型別參數U
的泛型方法,它會建立建構型G<U>
別的實例,並在該實例上呼叫 方法M
。 若要發出函式呼叫,您需要 MethodInfo 物件,表示 M
在建構型別上,換句話說,它會傳回型別,而不是型 U
別 T
。 若要這樣做,請先在 物件上TypeBuilder呼叫 MakeGenericType 方法,並GenericTypeParameterBuilder指定 表示U
為類型自變數的物件。
GetMethod然後使用 方法的MakeGenericType傳回值呼叫 方法做為 參數type
,以及MethodBuilder表示T M()
為 參數 method
的物件。 傳回值是 MethodInfo 您需要發出函式呼叫的物件。 程式代碼範例示範類似這樣的案例。