创建一个包罗万象的委托
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(...),但它只会为该参数采用一个函数。
我正在实现一个需要传递运行时未知的特定委托类型的函数。我想要 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(...),但它只会为该参数采用一个函数。