Инъекция зависимости - я не понимаю! - PullRequest
5 голосов
/ 25 февраля 2011

Хорошо, так что я играл с Ninject, «Сервисным слоем» и «Хранилищным слоем».

Я создал простое консольное приложение, чтобы поиграть, вот что я придумал:

Imports Ninject

Module Module1

    Sub Main()
        Dim Kernel As IKernel = New StandardKernel(New CustomerModule)
        Dim Service = Kernel.Get(Of CustomerService)()
        Console.WriteLine(Service.GetCustomerByID(1).Name)
        Console.Read()

    End Sub

End Module

#Region "Services"

Public Class CustomerService
    Private _Repository As ICustomerRepository

    <Inject()> _
    Public Sub New(ByVal Repository As ICustomerRepository)
        _Repository = Repository

    End Sub

    Public Function GetCustomerByID(ByVal ID As Integer) As Customer
        Return _Repository.GetByID(ID)
    End Function

End Class

#End Region

#Region "Repositories"

Public Interface IRepository(Of T)
    Function Query(ByVal Predicate As Expressions.Expression(Of Func(Of T, Boolean))) As IQueryable(Of T)
    Function GetByID(ByVal ID As Integer) As T

End Interface

Public Interface ICustomerRepository
    Inherits IRepository(Of Customer)

End Interface

Public Class CustomerRepository
    Implements ICustomerRepository

    Public Function GetByID(ByVal ID As Integer) As Customer Implements IRepository(Of Customer).GetByID
        Return New Customer With {.ID = ID, .Name = "Sam Striano"}
    End Function

    Public Function Query(ByVal Predicate As System.Linq.Expressions.Expression(Of System.Func(Of Customer, Boolean))) As System.Linq.IQueryable(Of Customer) Implements IRepository(Of Customer).Query
        Return Nothing
    End Function

End Class

#End Region

#Region "Domain Objects"

Public Class Customer
    Public Property ID As Integer
    Public Property Name As String
End Class

#End Region

#Region "Ninject Modules"

Public Class CustomerModule
    Inherits Modules.NinjectModule

    Public Overrides Sub Load()
        Bind(Of ICustomerRepository).To(Of CustomerRepository)()

    End Sub

End Class

#End Region

Мой вопрос или, как мне кажется, отсутствие понимания, заключается в методе Main () модуля:

Sub Main()
    Dim Kernel As IKernel = New StandardKernel(New CustomerModule)
    Dim Service = Kernel.Get(Of CustomerService)()
    Console.WriteLine(Service.GetCustomerByID(710615).Name)
    Console.Read()

End Sub

Почему бы просто не сделать это:

Sub Main()
    Dim Service = New CustomerService(New CustomerRepository)
    Console.WriteLine(Service.GetCustomerByID(710615).Name)
    Console.Read()

End Sub

Ответы [ 2 ]

9 голосов
/ 25 февраля 2011

По сути, вы спрашиваете, почему вы должны использовать DI-контейнер вместо Чистый DI .

DI действительно просто набор принципов и шаблонов , которые позволяют слабая связь .Вы можете использовать эти шаблоны для создания приложения независимо от какого-либо конкретного контейнера .

Однако, поскольку приложение становится все сложнее, особенно когда вам необходимо управлять различными стилями жизни из ваших компонентов DI-контейнер - отличный инструмент, который решает многие проблемы, которые в противном случае вам пришлось бы решать вручную.

4 голосов
/ 25 февраля 2011

Внедрение зависимостей позволяет вам отделить определенные реализации объектов от их интерфейсов. Это трудно оправдать в большинстве маленьких примеров, но для больших систем это может спасти жизнь. Это также может помочь вам изолировать ваши объекты в модульных тестах.

Например, если вы хотите написать тесты для своего класса CustomerService, вы можете легко добавить MockRepository вместо CustomerRepository. Это позволит вам тестировать CustomerService, не тестируя также CustomerRepository.

Вне модульного тестирования, я думаю, самый простой пример для визуализации может быть, если вы пишете модуль доступа к данным для вашего приложения. Возможно, вы захотите поддерживать SQL Server и MySQL. Затем вы создадите интерфейсы для ваших объектов доступа к данным и создадите их конкретные реализации для обеих систем баз данных. Эти реализации могут быть внедрены во время выполнения, таким образом:

Function Setup(ByVal dbType As String) As IKernel
    Dim dbModule As NinjectModule
    If dbType = "SQL Server" Then
        dbModule = New SQLServerModule
    Else If dbType = "MySQL" Then
        dbModule = New MySQLModule
    End If

    Return New StandardKernel(dbModule)
End Function

Это также позволяет добавлять поддержку других баз данных в будущем, изолируя детали реализации от остальной части приложения.

...