Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection - I don't get it!

Ok, so I was playing around with Ninject, a "Service Layer" and a "Repository Layer".

I built a simple console application to to play around, this is what I came up with:

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

My question, or I guess my lack of understanding, lies in Main() method of the module:

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

Why not just do this:

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

End Sub
like image 734
Sam Avatar asked Feb 24 '11 21:02

Sam


People also ask

How can I get dependency injection?

The injector class injects dependencies broadly in three ways: through a constructor, through a property, or through a method. Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.

Is dependency injection an overkill?

Of course. If you have a really small project with 12 classes, then a DI framework is almost certainly overkill.

What is the problem with dependency injection?

One problem with constructor injection is that if your class has many dependencies, then your constructor signature gets unwieldy and hard to read. Now, when you have multiple dependencies that you need to inject, each one is a separate set method and so we don't have a long list of constructor parameters.


2 Answers

Basically, you are asking why you should use a DI Container instead of Pure DI.

DI is really just a set of principles and patterns that enable loose coupling. You can use those patterns to compose an application irrespective of any particular container.

However, as an application grows in complexity, and particularly when you need to manage differing lifestyles of your components, a DI Container is an excellent tool that addresses many issues that you'd otherwise have to address manually.

like image 112
Mark Seemann Avatar answered Oct 07 '22 11:10

Mark Seemann


Dependency injection lets you decouple specific implementations of objects from their interfaces. It is difficult to justify in most of the small examples out there, but for larger systems it can be a life-saver. It can also help you to isolate your objects in unit tests.

For example, if you wanted to write tests for your CustomerService class, you could easily inject a MockRepository instead of CustomerRepository. This would let you test CustomerService without also testing CustomerRepository.

Outside of unit testing, I think the easiest example to visualize might be if you were writing a data access module for your application. You might want to support SQL Server and MySQL. You would then create Interfaces for your data access objects and create specific implementations of them for both database systems. Those implementations could be injected at runtime, thusly:

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

This also enables you to add support for other databases in the future, isolating the implementation details from the rest of the application.

like image 27
Tony Casale Avatar answered Oct 07 '22 11:10

Tony Casale