2017-08-24 61 views
4
Public Class LoginManager 
    Implements ILoginManager 
    Private ReadOnly _iLoginRepository As ILoginRepository 
    Public Sub New() 
     _iLoginRepository = New LoginRepository() 
    End Sub 

    Public Async Sub InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) Implements ILoginManager.InsertFailedLoginAttempt 
     'Example of the S in Solid (Single Repsonsibilty) 
     'Need to call these method async. But await errors 
      _iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt) 
      _iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt) 
     End Sub 
    End Class 

Repsoitory接口:如何在VB.NET中編寫Async Sub?

Public Interface ILoginRepository 
    Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean) 
    Sub InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin) 
    Sub InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin) 

End Interface 

倉庫實現:

Public Class LoginRepository 
    Implements ILoginRepository 
    Public ReadOnly _applicationDBContext As New ApplicationDBContext() 

    Public Async Sub InsertFailedLoginAttemptAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptAsync 
     Using _applicationDBContext 
      _applicationDBContext.RepFailedLogins.Add(failedLoginAttempt) 
      Await _applicationDBContext.SaveChangesAsync() 
     End Using 
    End Sub 

    Public Async Sub InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt As FailedLogin) Implements ILoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync 
     Using _applicationDBContext 
      _applicationDBContext.RepFailedLoginMasters.Add(failedLoginAttempt) 
      Await _applicationDBContext.SaveChangesAsync() 
     End Using 
    End Sub 

    ''' <summary> 
    ''' Determine whether a user is authenticated, be it an internal or external user 
    ''' I have condensed two methods into one 
    ''' </summary> 
    ''' <param name="cID"></param> 
    ''' <param name="password"></param> 
    ''' <param name="IsExternalUser"></param> 
    ''' <returns></returns> 
    Public Async Function IsUserAuthenticatedAsync(cID As String, password As String, IsExternalUser As Boolean) As Task(Of Boolean) Implements ILoginRepository.IsUserAuthenticatedAsync 
     If (IsExternalUser And String.IsNullOrEmpty(password)) Then 
      Throw New ArgumentNullException("External user requires password") 
     End If 

     Dim user As Chaser 
     Dim toRet As Boolean 

     Using _applicationDBContext 
      'Two ways to use LINQ 
      'First is LINQ Lambda sybntax(little harder to read) 
      user = Await _applicationDBContext.Chasers.Where(Function(x) x.CID = cID).FirstOrDefaultAsync() 

      'Second is LINQ Query syntax(looks more like SQL just more verbose 
      'user = From x In _applicationDBContext.Chasers 
      '  Where x.CID = cID 
      '  Select x 
     End Using 

     If IsNothing(user) Then 
      toRet = False 
     ElseIf Not IsExternalUser And Not IsNothing(user) Then 
      toRet = True 
     ElseIf IsExternalUser And user.Hash_Password = password Then 
      toRet = True 
     End If 

     Return toRet 
    End Function 
End Class 

我想打電話給我的經理InsertFailedLoginAttemptAsync庫方法。這是一種異步方法,但我無法等待該方法。我怎樣才能使這個方法等待?

我相信它與接口有關,並沒有像C#那樣使它成爲異步方法,但我無法做到這一點。

+1

'Sub's不應該是異步。事件處理程序是該規則的唯一例外。您等待只能從「功能」返回的「任務」。如果意圖是使接口異步,那麼所有成員都需要是返回「任務」或其衍生物的函數。 – Nkosi

回答

2

Sub,不應爲異步。事件處理程序是該規則的唯一例外。您等待Task,只能從Function返回。如果意圖是使該接口異步,則所有成員都需要是返回Task或其派生項的函數。

異步是在使用時一直冒泡的東西。也就是說ILoginManagerILoginRepository應該重構(如果可能的話)以遵循正確的語法。

參考:Async/Await - Best Practices in Asynchronous Programming

2

通過恩科西的答覆修正:

接口:

Public Interface ILoginRepository 
    Function IsUserAuthenticatedAsync(ByVal cID As String, ByVal password As String, ByVal IsExternalUser As Boolean) As Task(Of Boolean) 
    Function InsertFailedLoginAttemptAsync(ByVal failedLoginAttempt As FailedLogin) As Task 
    Function InsertFailedLoginAttemptIntoLoginMasterAsync(ByVal failedLoginAttempt As FailedLogin) As Task 

End Interface 

管理方法:

Public Async Function InsertFailedLoginAttempt(failedLoginAttempt As FailedLogin) As Task Implements ILoginManager.InsertFailedLoginAttempt 
     'Example of the S in Solid (Single Repsonsibilty) 
     Await _iLoginRepository.InsertFailedLoginAttemptAsync(failedLoginAttempt) 
     Await _iLoginRepository.InsertFailedLoginAttemptIntoLoginMasterAsync(failedLoginAttempt) 
    End Function