如何查找Action的参数类型(使用反射)?

时间:2012-12-03 12:19:51

标签: .net vb.net reflection parameters action

我有一个方法,将一系列操作作为参数。此数组中的操作应始终需要1个参数,但参数类型可能不同

该方法应在调用之前检查操作所需的参数类型。如果需要String,则参数将为"text"。如果需要Integer,则参数将为123

这是我尝试过的:

Sub MethodA(ParamArray actions() As Action(Of Object))
  For Each action() As Action(Of Object) In actions
    If action.Method.GetParameters()(0).ParameterType = GetType(String) Then
      action("text")
    ElseIf action.Method.GetParameters()(0).ParameterType = GetType(Integer) Then
      action(123)
    ElseIf ...
      ' You get the point.
    End If
  Next
End Sub

但是,action.Method.GetParameters()(0).ParameterType总是Object,可能是因为MethodA的参数数组只需要Action(Of Object)

由于我的代码不起作用,我还能尝试什么?如何找到真正所需的操作类型?

注意:我可以使用Try ... Catch,但我想确定不需要调用方法所需的参数类型。

修改:我发现我不理解Action(Of T)AddressOf的行为,这可能与我的问题有关。请参阅以下代码:

Sub MyStringMethod(s As String)
  ' Do something
End Sub

MethodA(AddressOf MyStringMethod) ' Compiles
Dim stringAction As Action(Of String) = AddressOf MyStringMethod
MethodA(stringAction) 'Does not compile

这有什么不同? AddressOf会生成Action(Of Object)吗?

1 个答案:

答案 0 :(得分:0)

问题是没有办法将Action(Of Object)变量设置为Action(Of String)Action(Of Integer)对象,例如:

Dim actions(2) As Action(Of Object)
'The following lines will not compile
actions(0) = New Action(Of String)(AddressOf MyStringMethod)
actions(0) = New Action(Of Integer)(AddressOf MyIntegerMethod)

所以问题不在于您检查类型的位置。问题是你首先不能将任何其他类型传递给方法,那么该方法怎么可能知道呢?

您需要通过创建包装类来传递每个操作的类型,例如:

Public Class MyAction
    Public Sub New(ByVal action As Action(Of Object), ByVal parameterType As Type)
        _action = action
        _type = Type
    End Sub

    Public ReadOnly Property Action() As Action(Of Object)
        Get
            Return _action
        End Get
    End Property
    Private _action As Action(Of Object)

    Public ReadOnly Property Type() As Type
        Get
            Return _type
        End Get
    End Property
    Private _type As Type
End Class

或者,如果数组中的所有项都采用相同的参数,那么您可以要求将类型作为方法的参数,例如:

Sub MethodA(ParamArray actions() As Action(Of Object), parameterType As Type)
    '...
End Sub

<强>更新

根据后续对话,您需要做的只是使用基本Delegate类型而不是Action(Of Object)类型。例如:

Sub MethodA(ParamArray actions() As [Delegate])
    '...
End Sub

但是,通过这样做,您允许传递具有其他类型签名的代理,例如,它将允许Function而不是Sub,或者方法为零参数或参数太多,而不是一个参数。因此,您可能需要在内部进行一些额外的检查,以确保代理的签名符合您的期望。