2017-05-08 96 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'不是硬编码的。 –