dependency-injection-pattern-in-csharp

Dependency Injection Pattern in C#

In this post I will explain Dependency Injection Pattern (DI), Dependency inversion principle (DIP), Inversion of control (IOC) and Dependency Injection Container with some examples code.

Dependency Injection Pattern (DI)

First of all, Dependency Injection Pattern is a SOFTWARE DESIGN PATTERN. It is called a “pattern’ because it suggests low-level specific implementation to a specific problem.

The main problem of this pattern aims to solve is, how to create loosely coupled components. It does that by separating the creation of components from their dependencies.

There are four main roles (classes) in this pattern:

  1. Client: The client is a component/class that wants to use services provided by another component, called Service.
  2.  Service-Interface: The service interface is an abstraction describing what kind of services Service component is providing.
  3. Service: Service component/class is providing services according to Service-Interface description.
  4. Injector:  InInjector Is a component/class that is tasked with creating Client and Service components and assembling them together.

The way it works is Client is dependent on Service-Interface. Client depends on IService interface but has no dependency on Service itself. Service implements IService interface and offers certain services that Client needs. Injector creates both Client and Service objects and assembles them together. We say that Injector injects Service into Client.

Here is a class diagram of this pattern:

dependency-injection-pattern-in-csharp-1.png

Here is a sample code of this pattern:

public interface IService
{
void UsefulMethod();
}
public class Service : IService
{
void IService.UsefulMethod()
{
//some useful work
Console.WriteLine("Service-UsefulMethod");
}
}
public class Client
{
public Client(IService injectedService = null)
{
//Constructor Injection
_iService1 = injectedService;
}
private IService _iService1 = null;
public void UseService()
{
_iService1?.UsefulMethod();
}
}
public class Injector
{
public Client ResolveClient()
{
Service S = new Service();
Client C = new Client(S);
return C;
}
}
internal class Program
{
static void Main(string[] args)
{
Injector injector = new Injector();
Client cli = injector.ResolveClient();
cli.UseService();
Console.ReadLine();
}
}

Types of Dependency Injection based on a Method of Injecting

One can find that they are mentioning different types of Dependency Injection, classified based on the method of injecting Service into Client. I think that is not such an important distinction since the effect is always the same, that is reference to Service is being passed to Client, no matter how. But, for completeness, let us explain it.

Types of Dependency Injection are:

  1. Constructor Injection: Injection is done in Client constructor
  2. Method Injection: Injection is done via a dedicated method
  3. Property Injection:  Injection is done via public property

Here is the code of each type:

public interface IService
{
    void UsefulMethod();
}
public class Service : IService
{
    void IService.UsefulMethod()
    {
        //some useful work
        Console.WriteLine("Service-UsefulMethod");
    }
}
public class Client
{
    public Client(IService injectedService = null)
    {
        //1.Constructor Injection
        _iService1 = injectedService;
    }
    public void InjectService(IService injectedService)
    {
        //2.Method Injection 
        _iService1 = injectedService;
    }
    public IService Service
    {
        //3.Property Injection
        set { _iService1 = value; }
    }
    private IService _iService1 = null;
    public void UseService()
    {
        _iService1?.UsefulMethod();
    }
}
public class Injector
{
    public Client ResolveClient()
    {
        Service S = new Service();
        //NOTE: This is tutorial/demo code, normally you
        //implement only one of these three methods
        //1.Constructor Injection
        Client C = new Client(S);
        //2.Method Injection 
        C.InjectService(S);
        //3.Property Injection
        C.Service = S;
        return C;
    }
}

Let us emphasize the main thing in this design pattern. That is the fact that Client is completely ignorant of the type of Service injected, it just sees interface IService and has no clue what version of Service is being injected. Let us look at the following class diagram:

dependency-injection-pattern-in-csharp-2.png

Client has no knowledge of which service is being injected, if it is Service1Service2 or Service3. That is what is wanted, we see that components/classes ClientService1Service2, and Service3 are loosely coupled.

Client class is now more reusable and testable. One typical usage of this feature is that in the production environment, Client is injected with real service Service1, and in the test, environment Client is injected Service2 which is a Mock service created just for testing.

Benefits of this Pattern

The benefits of this pattern are:

  • Creation of loosely coupled components/classes Client and Service
  • Client has no dependency nor knowledge of Service which makes it more reusable and testable
  • Enables parallel development of components/classes Client and Service by different developers/teams since the boundary between them is clearly defined by the IService interface
  • It eases the unit-testing of components

Disadvantages that this pattern brings are:

  • More effort to plan, create and maintain an interface
  • Dependency on Injector to assemble components/classes

Dependency Inversion Principle (DIP)

The Dependency inversion principle (DIP) is a SOFTWARE DESIGN PRINCIPLE. It is called principle because it provides high-level advice on how to design software products.

DIP is one of five design principles known under the acronym SOLID [3] promoted by Robert C. Martin [5]. The DIP principle states:

  1. High-level modules should not depend on low-level modules. Both should depend on the abstraction.
  2. Abstractions should not depend on details. Details should depend on abstractions.

Interpretation:

While high-level principle talks about abstraction, we need to translate that into terms in our specific programming environment, in this case, C#/.NET. Abstractions in C# are realized by interfaces and abstract classes. When talking about “details”, the principle means “concrete implementations”.
So, basically, that means that DIP promotes the usage of the interfaces in C# and concrete implementations (low-level modules) should depend on interfaces.

Traditional module dependencies:

DIP proposes with this new plan:

As you can see, some dependencies (arrows) have inverted directions, so that is where the name “inversion” comes from.

The goal of DIP is to create “loosely coupled” software modules. Traditionally, high-level modules depend on low-level modules. DIP has a goal to make high-level modules independent of low-level modules’ implementation details. It does that by introducing an “abstract layer” (in the form of an interface) between them.

Dependency Injection Pattern ,follows this principle and is often mentioned as closely related to DIP realization. But the DIP principle is a broader concept and has an influence on other design patterns. For example, when applied to the Factory design pattern or Singleton design pattern, it suggests that those patterns should return a reference to an interface, not a reference to an object.

Inversion of Control (IoC)

The Inversion of control (IoC) is a SOFTWARE DESIGN PRINCIPLE. It is called “principle” because it provides high-level advice on how to design software products.

In traditional programming, a custom code always has flow control and calls libraries to perform tasks.
The IoC principle proposes that (sometimes) flow of control be given to the “framework” which will call custom code to perform tasks.

When they say “framework”, they mean a specialized, arbitrary complex reusable module/library that is designed for a specific task, and custom code is written in a manner so it can work with that “framework”. We say that the “flow of control is inverted” since now “framework” calls into custom code.

The framework plays the role of the main program in controlling application activity. The main control of the program is inverted, moved away from you to the framework. Inversion of control is a key part what makes a framework different from a library

he IoC principle promotes the development and usage of reusable “software frameworks” that implement common scenarios. Then, problem-specific custom code is written and made to work together with the “framework” to solve a specific task.

While IoC principle is often mentioned in the context of Dependency Injection Pattern which follows it, it is a much broader concept. For example, an “UI framework” based on event handlers/callback methods also follows IoC principle. See [26], [25], [8] for more explanation.

Dependency Injection Pattern  follows this principle since the normal traditional approach is for Client to create Service and establish dependency. Here control is inverted, that is the creation of Service and the creation of dependency are delegated to the Injector, which in this case is the “framework”

Dependency Injection Container

Dependency Injection Container (DI Container) is a SOFTWARE MODULE/LIBRARY that enables automatic Dependency Injection with many advanced options.

In the terminology of IoC principle, DI Container has the role of the “framework” so often you will see it referred to as “DI framework”, but my opinion is that the framework word is overused and it leads to confusion (you have ASP MVC framework, DI framework, Entity Framework, etc.).

Often in literature, it is referred to as IoC Container, but I think IoC principle is a broader concept than the DI pattern , and here we are taking really of the DI pattern implementation on a large scale. So, DI Container is a much better name, but the name IoC Container is very popular and is broadly used for the same thing.

What is DI Container

DI Container is an advanced module/library that serves as an Injector for many Services at the same time. It enables the implementation of DI pattern on a large scale, with many advanced functions. DI Containers are a very popular architectural mechanism and many popular frameworks such as ASP MVC plan for and enable the integration of DI Containers.

The most popular DI Containers are Autofac  Unity , Ninject , Castle Windsor  etc.

DI Container functions

DI Container will offer functions:

Register Mappings. You need to tell the DI Container mappings between abstraction (interfaces) to concrete implementations (classes) so that it can properly inject proper types. Here, you feed the container with basic info it needs to work.

Mange objects Scope and Lifetime. You need to tell the container what scope and lifetime will object it creates have.
Typical lifestyle patterns are:

  1. Singleton: A single instance of the object is always used.
  2. Transient: Every time a new instance of an object is created.
  3. Scoped: That is typically a singleton pattern per an implicitly or explicitly defined scope.

You need to tell the container for example if you want every time it resolves dependency a new object to be created or if you want a singleton pattern applied. And singleton can be, for example, per process, per thread, or per user-defined scope. Also, you need to specify the desired lifetime of your object. You can configure, for example, object lifetime per process, or object lifetime to be per user-defined scope, meaning the object will be disposed of at the end of the scope that the user defines. The container can enforce all that, just needs to be precisely configured.

Resolve Method. Here is the actual work of creating and assembling the required object/type being done. The container creates an object of the specific type, resolves all the dependencies, and injects them into the created object. The method works recursively into depth until all the dependencies are resolved. DI Container does the work of resolving the dependencies by using technologies like Reflection and similar.

DI Container, Autofac Example

One of the most used DI Containers in C# world is Autofac . We will show a simple example of how it works.

Here is our class diagram:

dependency-injection-pattern-in-csharp-5.png

Example code:

public interface IService
{
}
public class Service : IService
{
    public Service()
    {
    }
}
public class Client
{
    public IService iService;
    public Client(IService injectedService)
    {
        iService = injectedService;
    }
}
internal class Program
{
    public static string MySerialize(object obj)
    {
        string serialized = null;
        var indented = Newtonsoft.Json.Formatting.Indented;
        var settings = new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.All
        };
        serialized = JsonConvert.SerializeObject(obj, indented, settings); //(5)
        return serialized;
    }
    static void Main(string[] args)
    {
        // Register mappings
        var builder = new Autofac.ContainerBuilder();
        builder.RegisterType<Service>().As<IService>(); //(1)
        builder.RegisterType<Client>().AsSelf();   //(2)
        Autofac.IContainer Container = builder.Build();    //(3)
        //Resolve object
        var client = Container.Resolve<Client>();     //(4)  
        // Json serialize object to see what we got
        Console.WriteLine(MySerialize(client)); //(5)
        Console.ReadLine();
    }

Execution output:

dependency-injection-pattern-in-csharp-6.png

As you can see, Autofac has its own API that we need to follow. At (1), we registered the mapping IService: Service. Then in (2), we registered the Client itself. At (3), we build the container and is ready for use. At (4), we do resolution and that is where the resolution of dependencies and injection is done.
In order to verify that we got an object we wanted, we serialize it  and print it out at (5).
If you look again at  and terminology there, then our class Client has the role of Client from class Service has the role of Service  and object Container has the role of Injector.

So, the point is ASP.NET MVC framework provides a registration point for dependency resolver. If you do not want to use DI, that is fine too. But, if you want to use DI in your ASP.NET MVC application, you can register your DI Container of choice with the application framework as shown above, and magically DI resolution will start to work in your application.

The codes examples are in my Github.

Conclusion

In this post, I have focused on the Dependency Injection Pattern (DI) and its industrial application Dependency Injection Container . I also explained related principles for software design, the Dependency Inversion Principle (DIP) and Inversion of Control (IoC) principle, and have showed some sample code using Autofac container.

Back to home page