Skip to main content

Dependency Injection

In software engineering, dependency injection is a software design pattern that implements inversion of control for resolving dependencies. A dependency is an object that is be used in a class as service. An injection is the passing of a dependency to a dependent object (a client) that would use it. The service is made part of the client’s state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.
Dependency injection allows a program design to follow the dependency inversion principle. The client delegates to external code (the injector) the responsibility of providing its dependencies. The client is not allowed to call the injector code. It is the injecting code that constructs the services and calls the client to inject them. This means the client code does not need to know about the injecting code. The client does not need to know how to construct the services. The client does not need to know which actual services it is using. The client only needs to know about the intrinsic interfaces of the services because these define how the client may use the services. This separates the responsibilities of use and construction.
Dependency injection separates the creation of a client’s dependencies from the client’s behavior, which allows program designs to be loosely coupled and to follow the dependency inversion and single responsibility principles. It directly contrasts with the service locator pattern, which allows clients to know about the system they use to find dependencies.
An injection, the basic unit of dependency injection, is not a new or a custom mechanism. It works in the same way that “parameter passing” works. Referring to “parameter passing” as an injection carries the added implication that it’s being done to isolate the client from details.
Dependency injection involves four roles:
  • the service object(s) to be used
  • the client object that is depending on the services it uses
  • the interface that define how the client may use the services
  • the injector, which is responsible for constructing the services and injecting them into the client
Any object that may be used can be considered a service. Any object that uses other objects can be considered a client. The names have nothing to do with what the objects are for and everything to do with the role the objects play in any one injection.
The interfaces are the types the client expects its dependencies to be. hey may truly be interface types implemented by the services but also may be abstract classes.
Given that the client has no concrete knowledge, so long as the what the client uses, the interfaces name and methods, then the client won’t need to change even if what is behind the interface changes. However, if the interface is refactored from being a class to an interface type (or vice versa) the client will need to be recompiled.This is significant if the client and services are published separately. This unfortunate coupling is one that dependency injection cannot resolve.
The injector introduces the services into the client. Often, it also constructs the client. An injector may connect together a very complex object graph by treating an object like a client and later as a service for another client. The injector may be referred to by other names such as: assembler, provider, container, factory, builder, spring, construction code, or main.

Advantages

  • Dependency injection allows a client to remove all knowledge of a concrete implementation that it needs to use. This helps isolate the client from the impact of design changes and defects. It promotes reusability, testability and maintainability.
  • Reduction of boilerplate code in the application objects since all work to initialize or set up dependencies is handled by a provider component.
  • Dependency injection allows concurrent or independent development. Two developers can independently develop classes that use each other, while only needing to know the interface the classes will communicate through. Plugins are often developed by third party shops that never even talk to the developers who created the product that uses the plugins.
  • Dependency Injection decreases coupling between a class and its dependency.

Disadvantages

  • Dependency injection creates clients that demand configuration details be supplied by construction code. This can be onerous when obvious defaults are available.
  • Dependency injection can make code difficult to trace (read) because it separates behavior from construction. This means developers must refer to more files to follow how a system performs.
  • Dependency injection forces complexity to move out of classes and into the linkages between classes which might not always be desirable or easily managed.
  • Ironically, dependency injection can encourage dependence on a dependency injection framework.
In the following C# example, the Client class contains a Service member variable that is initialized by the Client constructor. The client controls which implementation of service is used and controls its construction. In this situation, the client is said to have a hard-coded dependency on ServiceExample.
// An example without dependency injection
public class Client {
    // Internal reference to the service used by this client
    private Service service;

    // Constructor
    public Client() {
        // Specify a specific implementation in the constructor 
        //instead of using dependency injection
        service = new ServiceExample();
    }

    // Method within this client that uses the services
    public String greet() {
        return "Hello " + service.getName();
    }
}
Dependency injection is an alternative technique to initialize the member variable rather than explicitly creating a service object as shown above.

Three types of dependency injection

There are at least three ways an object can receive a reference to an external module:
  • constructor injection: the dependencies are provided through a class constructor.
  • property injection: the client exposes a property that the injector uses to inject the dependency.
  • interface injection: the dependency provides an injector method that will inject the dependency into any client passed to it. Clients must implement an interface that exposes a property that accepts the dependency.

Constructor injection

This method requires the client to provide a parameter in a constructor for the dependency.
// Constructor
Client(Service service) {
    // Save the reference to the passed-in service inside this client
    this.service = service;
}

Setter injection

This method requires the client to provide a property for each dependency.
// Property
public void setService(Service service) {
    // Save the reference to the passed-in service inside this client
    this.service = service;
}

Interface injection

This is simply the client publishing a role interface to the property of the client’s dependencies. It can be used to establish how the injector should talk to the client when injecting dependencies.
// Service interface.
public interface ServiceSetter {
    public void setService(Service service);
}

// Client class
public class Client : ServiceSetter {
    // Internal reference to the service used by this client.
    private Service service;

    // Set the service that this client is to use.
    @Override
    public void setService(Service service) {
        this.service = service;
    }
}

Comments

Popular posts from this blog

Accessing File Stored in Windows Azure Blob Storage Using jQuery

Did you know it was possible to access the Windows Azure Blob Storage directly from JavaScript, for example using jQuery? At first, it sounds obvious, since Blobs are after all accessible from a public UR. But in practice, there is a very big hurdle: the Web browser’s Same Origine Policy or SOP, that restricts JavaScript code to accessing resources originating from the same site the script was loaded from. This means that you will never be able to load a Windows Azure Blob using XMLHttpRequest for example! Fortunately, there is a popular workaround called JSONP (“JSON with Padding”). The idea behind this technique is that the script tag is not submitted to the SOP: an HTML page can thus load a JavaScript file from any site. So, if you expose your data in an “executable” form in JavaScript, a page will be able to load this data using a script tag. For example: <script type=”text/javascript” src=”http://www.sandeepknarware.in/exemple.jsonp”> </script> But how can ...

Support for debugging lambda expressions with Visual Studio 2015

Anyone who uses LINQ (or lambdas in general) and the debugger will quickly discover the dreaded message “Expression cannot contain lambda expressions”. Lack of lambda support has been a limitation of the Visual Studio Debugger ever since Lambdas were added to C# and Visual Basic.  With visual studio 2015 Microsoft has added support for debugging lambda expressions. Let’s first look at an example, and then I’ll walk you through current limitations. Example To try this yourself, create a new C# Console app with this code: using System.Diagnostics; using System.Linq; class Program { static void Main() { float[] values = Enumerable.Range(0, 100).Select(i => (float)i / 10).ToArray(); Debugger.Break(); } } Then compile, start debugging, and add “values.Where(v => (int)v == 3).ToArray()” in the Watch window. You’ll be happy to see the same as what the screenshot above shows you. I am using Visual Studio 2015 Preview and it has some limitati...

gcAllowVeryLargeObjects Element

There are numerous new features coming with .NET 4.5 and here, on this blog, you can find several posts about it. But the feature we are goint to talk about today is very exciting, because we were waiting for it more than 10 years. Since .NET 1.0 the memory limit of .NET object is 2GB. This means you cannot for example create array which contains elements with more than 2GB in total. If try to create such array, you will get the OutOfMemoryException. Let’s see an example how to produce OutOfMemoryException. Before that Open Visual Studio 2012, and create C# Console Application, like picture below. First lets create simple struct with two double members like example below: 1 2 3 4 5 6 7 8 9 10 11 12 public struct ComplexNumber {      public double Re;      public double Im;      public ComplexNumber( double re, double im)      {    ...