创建一个包罗万象的代表

时间:2015-01-19 20:10:20

标签: .net vb.net delegates

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

使用'真实'委托,以下代码工作正常:

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。有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

我根据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(...),但是它只会为该参数获取一个函数。