VB.net属性可以递归调用自身吗?

时间:2017-05-02 18:47:47

标签: .net vb.net recursion mvp

所以我们在VB.net中使用MVP设计模式。我们有一个简单的登录视图和界面:

Public Interface ILogonView
    ReadOnly Property Username() As String
End Interface

Public Class LogonView
    Implements ILogonView
    Public ReadOnly Propery Username As String Implements ILogonView.Username
        Get
            tbUsername.Text
        End Get
    End Property
End Class

问题是我们需要修改Get以使其具有线程安全性。这样做意味着我们需要有选择地将代码包装在Control.Invoke()调用中,以确保我们只能从主线程访问UI对象。

例如,如果不是使用Property执行此操作,而是使用标准getter执行此操作,我们将使用递归。类似的东西:

Function GetUsername() as String
    If Me.InvokeRequired Then
        Return Me.Invoke(Sub() GetUsername())
    End If
    Return tbUsername.Text
End Function

我的问题是 - 我们可以从属性的Getter中递归调用一个属性吗?我的Vb.net有点生疏,我无法发现完成此任务的语法魔法。

2 个答案:

答案 0 :(得分:3)

是,不需要调用时返回。如果在第一次通过时需要,则后续通话不会。

Public ReadOnly Property GetUsername As String
    Get
        If tbUsername.InvokeRequired Then
            Return tbUsername.Invoke(Function() GetUsername())
        Else
            Return tbUsername.Text
        End If
    End Get
End Property

请参阅Automating the InvokeRequired code pattern

您可以编写扩展方法来自动化

<Extension()>
Public Function InvokeIfRequired(Of TR)(ByVal control As Control, func As Func(Of TR)) As TR
    If control.InvokeRequired Then
        Return CType(control.Invoke(func), TR)
    Else
        Return func()
    End If
End Function

<Extension()> _
Public Sub InvokeIfRequired(ByVal control As Control, action As MethodInvoker)
    If control.InvokeRequired Then
        control.Invoke(action)
    Else
        action()
    End If
End Sub

然后

Public Property GetUsername As String
    Get
        Return tbUsername.InvokeIfRequired(Function() tbUsername.Text)
    End Get
    Set(value As String)
        tbUsername.InvokeIfRequired(Sub() tbUsername.Text = value)
    End Set
End Property

您可以在Project Property Pages&gt;&gt;中忽略与项目中的递归属性调用相关的编译器警告。编译&gt;&gt;警告配置&gt;&gt; Recursive operator or property access = None,但它适用于整个项目可能弊大于利。

答案 1 :(得分:0)

非递归方法

Public ReadOnly Property GetUsername As String
    Get
        Dim rv As String
        If tbUsername.InvokeRequired Then
            tbUsername.Invoke(Sub()
                                  rv = tbUsername.Text
                              End Sub)
        Else
            rv = tbUsername.Text
        End If
        Return rv
    End Get
End Property