如何传递具有多个参数的方法作为另一个方法的参数

时间:2015-11-06 15:31:35

标签: .net vb.net func

我有多种不同的方法,我无法编辑:

    Public Function Test1(A As Integer, B As String, C As Boolean) As Boolean
    Public Function Test2(A As Boolean, B As Double) As DataTable
    Public Function Test3(A As String) As Integer

我开始创建一个这样的类:

Public Class MyWrapperClass

    Dim _method As Action()

    Public Sub New(Method As Action())
        _method = Method
    End Sub

    Public ExecuteFunction()
        _method()
        ' And do something with the result
    End Function

End Class

问题是:

如何传递具有某些参数的Method并在ExecuteFunction中调用它们?我尝试使用Action,但它不符合其定义和用法。

例如,我想做这样的事情:

Dim test1 = new MyWrapperClass(Test1)
test1.ExecuteFunction(1, "test1", true)

Dim test2 = new MyWrapperClass(Test2)
test2.ExecuteFunction(true, 0.34)

有可能吗?我怎样才能获得这种效果/我应该使用哪种模式?

1 个答案:

答案 0 :(得分:2)

How can I pass a Method that has some arguments

问题是创建和使用MyClassWrapper的代码没有传入任何参数,并且由于Action没有返回,如果你需要返回,它不是正确的选择。

该示例显示为每个方法创建一个新的对象包装器,这似乎效率低下。为简单起见,我将参数更改为您无权访问的类的基本类型:

Public Function Test1(A As Integer, B As String, C As Boolean) As Int32
Public Function Test2(A As Boolean, B As Double) As String
Public Function Test3(A As String) As Integer

不同的名称​​似乎表示目标方法重载,但MyWrapperClass似乎想要与它们交互,就好像它们是通过使用同名ExecuteFunction。即使问题代码是为了在此发布而设计的,CantEditClass也暴露了3种不同的方法。我不确定它是否清楚地必须辨别出哪个方法被参数的顺序/类型调用。

基本答案

直接将函数的地址传递给Wrapper方法。为此,可以使用Func()声明包装器方法,以定义链接到的方法:

Public Function Test1Exec(f As Func(Of Int32, String, Boolean, Int32), a As Int32) As Int32
    Dim n As Int32 = f(a, "foo", False)
End Function

用法:

Private wrapper As Wrapper
Private objSealed As CantEditClass
...
wrapper = New Wrapper
objSealed = New CantEditClass   
...
Dim b = wrapper.Test1Exec(AddressOf objSealed.Test1, 6)

声明重用代表

' declared with the other objects
Private fDel As Func(Of Int32, String, Boolean, Int32) 
...
' initialized:
fDel = AddressOf objSealed.Test1
...
Dim b = wrapper.Test1Exec(fDel, 6)  

如果在某个类/表单级别声明,fDel委托可以设置一次。如果重新创建objSealed,则代码将需要重置委托。特别是通用名称或准超载,命名的Delegate可以帮助您跟踪哪个是。

两者都相当麻烦,因为负担被消耗在代码上。

委派为包装类型

你也可以拥有包装"抓住"代表。在Wrapper

Public Delegate Function Test1Delegate(a As Int32, b As String, c As Boolean) As Int32
Public Function Test1aExec(f As Test1Delegate, a As Int32) As Int32
    Dim n As Int32 = f(a, "foo", False)
End Function    

用法:

Dim fDel2 As Wrapper.Test1Delegate = AddressOf objSealed.Test1
...
b = wrapper.Test1aExec(fDel2, 6)    

稍微不那么累赘。你也可以让包装器设置所有这些并通过在构造函数中传递密封的类对象来保持它们:

Private Delegate Function Test2Delegate(a As Boolean, b As Double) As String
Private Test2D As Test2Delegate

Private Delegate Function Test3Delegate(a As String) As Integer
Private Test3D As Test3Delegate

Public Sub New(target As CantEditClass)
    ' internal assignment
    Test2D = AddressOf target.Test2
    Test3D = AddressOf target.Test3
End Sub

智能包装,无代表

如果与Wrapper方法一起调用哪些变量,代表可能会有意义。如果没有,Wrapper可能会更聪明一点:

Public ReadOnly TargetObject As CantEditClass
' alternatively pass the object 
' if the calling code needs it for something like events
Public Sub New()
    ' internal mapping
    Dim TargetObject = New CantEditClass
End Sub

Public Function Text1Ex(arg1 As Int32, arg2 As String, arg3 As Boolean) As Int32
    Dim result = TargetObject.Test1(arg1, arg2, arg3)
    ' work with result
    Return If(arg3, arg1, -arg1)
End Function

代码可以轻松调用任一版本:

MyWrap = New Wrapper()

' call EXtended wrapper version
Dim result = MyWrap.Text1Ex(42, "ziggy", False)
' invoke the native version:
result = MyWrap.TargetObject.Test1(42, "zalgo", True)