2017-05-08 97 views
0

我正在學習依賴注入。在閱讀了很多文章並使用了一本書之後,下面的代碼基於我讀過的內容以及書中的一個例子。這個控制檯程序有效。在繼續學習更多關於DI的知識並在單元測試中使用之前,我想確認一下我是否正確理解它,以及是否正確編寫它。這個依賴注入示例和解釋是否正確?

主要

Sub Main() 

    Dim myWriter As IMessageWriter     'myWriter must be same type as ConsoleMessageWriter, next line. That is INTERFACE type IMessageWriter 
    myWriter = New ConsoleMessageWriter()   'myWriter INSTANCE is required to construct MyConsoleWriter INSTANCE below 

    Dim myConsoleWriter As ConsoleWriter   'myConsoleWriter must be same type as ConsoleWriter, next line. That is CLASS type ConsoleWriter 
    myConsoleWriter = New ConsoleWriter(myWriter) 'myConsoleWriter INSTANCE contructed w/ myWriter INSTANCE. myConsoleWriter exposes ConsoleWrite 

    myConsoleWriter.ConsoleWrite("Hello DI world.", True) 'INSTANCE myConsoleWriter's ConsoleWrite method uses INSTANCE MyWriter's Write method 
End Sub 

ConsoleWriter

Public Class ConsoleWriter 

    Private ReadOnly writer As IMessageWriter 

    Public Sub New(writer As IMessageWriter) 
    If writer Is Nothing Then 
     Throw New ArgumentNullException("writer") 
    End If 
    Me.writer = writer 
    End Sub  

    Public Sub ConsoleWrite(message As String, pause As Boolean) 
    Me.writer.Write(message, pause) 
    End Sub 
End Class 

ConsoleMessageWriter

Public Class ConsoleMessageWriter 
    Implements IMessageWriter 

    Public Sub Write(message As String, pause As Boolean) Implements IMessageWriter.Write 

    If pause Then 
     Console.WriteLine(message) 
     Console.WriteLine("<press any key to continue>") 
     Console.ReadKey() 
    Else 
     Console.WriteLine(message) 
    End If 

    End Sub 
End Class 

IMessageWriter

Public Interface IMessageWriter 
    Sub Write(message As String, pause As Boolean) 
End Interface 

我在上面的代碼中添加了一些註釋,以提醒我爲什麼每一步都被採用,下面的圖片是我爲了理解這種方法而創建的圖片。 enter image description here

我的問題很簡單。代碼有什麼問題嗎?代碼中的註釋?圖形?關於代碼,我知道有幾行可以合併,但是爲了增強我的基本理解,我把它們分開了。

謝謝。

回答

1

您的代碼正確地演示了依賴注入的概念,並且您的圖正確地演示瞭如何執行myConsoleWriter.ConsoleWrite調用。我唯一會改變的是你的評論,說myWriter must be same type as ConsoleMessageWriter, next line. That is INTERFACE type IMessageWriter這不是很準確。 myWriter不必是ConsoleMessageWriter類型,它只是一個實現IMessageWriter的類型。所以如果你有Public Class OtherConsoleMessageWriter Implements IMessageWriter,那麼myWriter也可以是OtherConsoleMessageWriter

話雖這麼說,請確保你明白,你的Main方法寫的方法就是證明注入的依賴到ConsoleWriter的這個概念,而在實際的項目,你不想做myWriter = New ConsoleMessageWriter() 。既然你在學習依賴注入,我認爲你還沒有涉及DI容器的話題。其要點是,你永遠不想明確創建你的依賴關係,因爲那樣你就把你的依賴關係硬編碼爲一個特定類型(你的情況爲ConsoleMessageWriter)。 DI容器將允許您配置容器,以便您可以告訴它哪個具體類型要爲每個接口返回,然後讓DI容器創建所有的依賴關係,但您會在閱讀更多內容時獲得該容器。

+0

Thx!我將我的第一條評論更改爲'myWriter必須實現與ConsoleMessageWriter相同的接口,下一行。這是INTERFACE類型IMessageWriter';更準確嗎?是的,我意識到我需要使用DI容器,並正在努力達到這個目標。以類似的方式看到DI容器是正確的,就像使用通常命名爲RelayCommand類的實現ICommand而不是實現ICommand的單個類一樣? – Alan

+0

我會將註釋更改爲'myWriter必須實現接口IMessageWriter',而不是在有關'ConsoleMessageWriter'的註釋中說什麼。由於依賴注入中的所有內容都只涉及接口,因此ConsoleWriter中的任何內容都不應該知道類ConsoleMessageWriter存在。 'ConsoleWriter'只關心給它一個實現'IMessageWriter'的依賴。 –

+0

DI容器與'RelayCommand'不同,它們滿足兩個無關的目的。DI容器的工作方式如下:在程序的開始的某個地方,在組合根中,連接所有的類和依賴項。所以當你創建你的'ConsoleWriter'對象時,你需要傳入一個實現'IMessageWriter'的對象。在你的例子中,你創建一個'新的ConsoleMessageWriter'。使用DI容器,您可以告訴容器創建一個實現「IMessageWriter」的對象,並將其作爲依賴項傳入。這樣'ConsoleMessageWriter'不是硬編碼的。 –