【问题标题】:Creating a catch-all delegate创建一个包罗万象的委托
【发布时间】:2015-01-23 04:15:32
【问题描述】:

我正在实现一个需要传递在运行时未知的特定委托类型的函数。我想返回一个以 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。有什么办法吗?

【问题讨论】:

  • GetType(Object()) 可以工作吗?
  • 否,因为等待 Delegate 的 AddHandler 例程需要完全匹配
  • 你最终想要做什么?这似乎是一种危险的编程方式。让我们进一步了解您的最终目标,也许我们可以帮助您找到比动态委托创建更好的解决方案。
  • @siride。我正在为 wpf 编写 MarkupExtension - 它设置在元素的事件“属性”上,并返回该事件的有效委托。它将绑定到数据模型上的给定方法签名。然而,中间的魔法直到运行时才知道委托类型。 [此外,我正在尝试将包罗万象的委托返回给元素,并将在内部将引发的事件传递给目标。这允许动态目标 - 如果数据模型中的对象发生更改,我不需要分离旧目标并附加新目标]

标签: .net vb.net delegates


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    相关资源
    最近更新 更多