创建一个包罗万象的委托

Creating a catch-all delegate

我正在实现一个需要传递运行时未知的特定委托类型的函数。我想要 return 一个将 ParamArray 作为其唯一参数的通用方法(该方法将用于调用另一个方法,将 ParamArray 作为其参数)。

使用 'real' 委托时,以下代码可以正常工作:

Public Sub OnEvent(ParamArray params()) 
    'Do work
End Sub

Function SomeFunc()
    Return New RoutedEventHandler(AddressOf OnEvent)
End Function

即使 OnEvent 与 RoutedEventHandler 的参数不匹配,这仍然有效 - 编译器可以使用 ParamArray,并正确传递参数。

然而,当使用 CreateDelegate 时,运行时抱怨参数不匹配:

Function SomeFunc()
   Return [Delegate].CreateDelegate(GetType(RoutedEventHandler), Me, "OnEvent")
End Function

实际代码会在运行时获取委托类型,所以我需要使用CreateDelegate。有什么办法吗?

我根据对 similar SO question 的回答编写了以下代码,针对 VB 进行了修改,并且更加简洁:

Imports System.Linq.Expression.Expressions 'this might only work in VS2015. You can use a explicit name instead, i.e. Expressions.Call, Expressions.Lambda

Public Shared Function GetDynamicDelegate(delegateType As Type, method As Action(Of Object())) As [Delegate]
        Dim invokeMethod = delegateType.GetMethod("Invoke")
        Dim params = invokeMethod.GetParameters.Select(Function(p) Parameter(p.ParameterType, p.Name)).ToArray
        Dim instance = If(method.Target Is Nothing, Nothing, Constant(method.Target)) 'Pass Nothing when Shared            
        Dim body = [Call](instance, method.Method, NewArrayInit(GetType(Object), params))
        Return Lambda(delegateType, body, params).Compile
End Function

(原来是一个额外的行投射到 Object() 但这是自动完成的,所以我把它漏掉了)

此函数仅采用方法 As Action(..)。您可以将其实现为 func 和 Func(...),但它只会为该参数采用一个函数。