背景:有一个泛型类,其中一个方法是泛型方法
Public Class GenericClass(Of T) 'This is not a generic method Public Sub Swap(ByRef item1 As T, ByRef item2 As T) Dim temp As T = item1 item2 = item1 item1 = temp End Sub 'This ia a generic method and a generic method definition Public Sub Swap(Of U)(ByRef item1 As U, ByRef item2 As U) Dim temp As U = item1 item2 = item1 item1 = temp End Sub Public Function GenericMethod(Of M)(ByVal item1 As M) As String Return String.Format("You Passed in {0}", item1) End Function End Class
现在的需求是,希望运用反射,在运行时,执行GenericMethod()方法
首先,提供一个显示泛型方法相关信息的方法
Private Sub DisplayGenericMethodInfo(ByVal mi As MethodInfo)
AddToResults("{0}", mi)
Dim indent1 As String = vbTab
Dim indent2 As String = vbTab & vbTab
AddToResults("{0} Is generic method definition :{1}", indent1, mi.IsGenericMethodDefinition)
AddToResults("{0} Is generic method {1}", indent1, mi.IsGenericMethod)
'获取一个值,该值指示当前Type对象是否具有尚未被特定类型替换的类型参数
AddToResults("{0} Includes unassigned generic parameters:{1}", indent1, mi.ContainsGenericParameters)
' if this is a generic method,displap its type arguments.
If mi.IsGenericMethod Then
'返回表示泛型类型的类型实参或泛型类型定义的类型形参的Type对象的数组
Dim args As Type() = mi.GetGenericArguments()
AddToResults("{0} Type arguments({1}):", indent2, args.Length)
For Each argType As Type In args
'IsGenericParameter is true only for generic type parameters
If argType.IsGenericParameter Then
AddToResults("{0}Parameters:{1}", indent2, argType)
'当Type对象表示泛型类型或泛型方法的类型参数时,
'获取类型参数在声明它的泛型类型或方法的类型参数列表中位置
AddToResults("{0}Parameters:{1}", indent2, argType.GenericParameterPosition)
AddToResults("{0}Declaring method:{1}", indent2, argType.DeclaringMethod)
Else
AddToResults("{0}{1}", indent2, argType)
End If
Next
End If
AddToResults()
End Sub
请注意上面代码中的关于判断一个泛型参数是泛型类型的参数,还是泛型方法的参数。它可能来自一个您正在检查的类型,也可能来自一个封闭类型,或者来自一个泛型方法。您如何确定他的来源?
首先,检查类型的DeclaringMethod属性。如果该值不是nothing,它就会是MethodInfo实例,您就知道该类型参数来自一个泛型方法,并且MethodInfo的IsGenericMethodDefinition属性将返回True.如果源不是一个泛型方法,DeclaringMethod属性就会返回Nothing,此时您可以检索DeclaringType属性。同时,只有在类型的IsGenericParameter属性返回True时,才能检索DeclaringMethod属性;否则会引发异常。
现在开始实现要求:
Private Sub CallGenericMethodGivenGenericMethodDefinition() Dim type1 As Type = GetType(GenericClass(Of Integer)) Dim mi As MethodInfo = type1.GetMethod("GenericMethod") DisplayGenericMethodInfo(mi) Dim argTypes() As Type = {GetType(String)} Dim miConstructed As MethodInfo = mi.MakeGenericMethod(argTypes) DisplayGenericMethodInfo(miConstructed) 'invoke the method ,createing an instance of the generic class first Dim host As New GenericClass(Of Integer) 'supply the method parameters,and then invoke the method: Dim args() As Object = {"test value"} AddToResults("{0}", miConstructed.Invoke(host, args)) AddToResults() 'construct another version of the same 'generic method ,this time taking an ineger as the parameter argTypes(0) = GetType(Integer) miConstructed = mi.MakeGenericMethod(argTypes) DisplayGenericMethodInfo(miConstructed) 'Supply the method parameters,and then invoke the method: args(0) = 13 AddToResults("{0}", miConstructed.Invoke(host, args)) End Sub