VB.NET - Hook机制,或者如何执行方法列表?

时间:2012-03-02 23:59:35

标签: vb.net

我有一个“总是”按顺序运行步骤A,C,D的算法。

我想允许一种方法来运行A,B,C,D,其中B可以是多种方法。 C,D“应该”不受影响,但我无法并行化。它只是写入文件。

无论如何,我对委托知之甚少,并使用AddressOf来挂钩事件处理程序。

所以我只想创建一个不包含“地址”或代表的数组或集合。

这甚至可能吗?

这是'最好'的方式吗?我知道如何强制使用对象的行为,但我希望重用已经内置于VB,.NET的任何机制。

戴恩

2 个答案:

答案 0 :(得分:1)

这不是您经常看到的内容,但您可以组合委托,以便单个委托变量在调用时调用多个函数。

Dim midAction As Action(Of String) = AddressOf Console.WriteLine
Dim m1 As New IO.StreamWriter(New IO.MemoryStream())
m1.AutoFlush = True
Dim m2 As New IO.StreamWriter(New IO.MemoryStream())
midAction = CType([Delegate].Combine(New Action(Of String)(AddressOf Console.WriteLine),
                                     New Action(Of String)(AddressOf m1.WriteLine),
                                     New Action(Of String)(Sub(s)
                                                             m2.WriteLine(s)
                                                             m2.Flush()
                                                           End Sub)), 
                  Action(Of String))
 midAction("test")

这里最大的问题是Delegate.Combine的无类型使得所有的演员阵容变得必要。

IEnumerable代表也可以工作,更强烈地传达您想要调用多个功能。

根据您的描述,我认为我会坚持使用单个委托参数,因为它似乎更适合参数的语义。当调用者有多个需要在中间调用的函数时,可以进行组合。

答案 1 :(得分:1)

您可以简单地使用事件来存储和调用多个方法。事件基本上是简化的多播代理,因此您不必使用Delegate.Combine。缺点是您的方法将无法返回类型。

这也是使用多播委托的另一种方法。此示例假定您希望从方法返回值。如果你不需要这个,你就不必循环使用这些方法;你可以使用myMethods.Invoke

'the methods will be stored here
Private _MyMethods As [Delegate]

'this is here to show the signature of the methods
Public Delegate Function MyMethod(ByVal input As String) As String

Public Sub AddMethod(ByVal method As MyMethod)
    _MyMethods = [Delegate].Combine(_MyMethods, method)
End Sub

Public Sub RemoveMethod(ByVal method As MyMethod)
    _MyMethods = [Delegate].Remove(_MyMethods, method)
End Sub

Public Sub InvokeMethods(ByVal input As String)
    If _MyMethods Is Nothing Then Return

    Dim myMethods As MyMethod = DirectCast(_MyMethods, MyMethod)

    'since you'll want the return value of each methods, loop through the methods
    For Each method As MyMethod In myMethods.GetInvocationList()
        Dim value As String = method.Invoke(input)

        'TODO: something with the value
    Next
End Sub

作为上述调用代码的另一种替代方法,您可以使用Delegate.DynamicInvoke方法来不必转换委托。但是,这将使用后期绑定,并且在函数的情况下,无论如何都需要返回值。