Saturday, May 09, 2020

APS.Net Core Dependency Injection





ASP.Net Core has a built-in dependency framework. This means you don't need to write your own plumbing code to achieve Dependency Injection. ASP.Net Core helps enforces the Dependency Injection Principle out of the box.   


What is a dependency?


Dependency is established between classes when one class needs another class to fulfil its functionality. Below are two classes class A and class B. Class A needs class B to accomplish the addition functionality. So class A has a dependency on class B or class A is dependent on class B.

class A{

    public int addition(int x, int y)
    {
        B objB = new B();
        return objB(x,y);
    }
}

While this is a perfectly viable situation to do, it makes class A very tightly coupled with class B. To further elaborate on this, imagine you discovered a faster algorithm in class C. You would now have to rewrite class A, remove the dependency on B and use C instead. While this doesn't seem difficult to do in their example it may not be the same if this dependency has been used in several places throughout your code. 


Dependency injection


Is there a better way to manage a dependency? Yes there is and its called Dependency Injection. Instead of letting class A manage the creation of class B, we delegate this responsibility to the class calling class A and then injecting that object into class A when required.  


class A{

    private B _objB;

    public A(B objB)
    {
        _objB = objB;
    }

    public int addition(int x, int y)
    {
        return _objB(x,y);
    }
}


class Program{

     public static void main(string args[])
     {
          B objB = new B();
          A objA = new A(objB);
          Console.WriteLine(obja.addition(4,5).ToString());
     }
}

Dependency injection in ASP.Core


ASP.Core has introduced a dependency injection container in the form of a ConfigureServices method in the Startup classLet's walk this through by creating and registering a service called MyService.



Step1: Create an interface for our service called IMyService.

interface IMyService{
     public void GetMyUsers();
}

Step2: Create a service called MyService that implements interface IMyService.

public class MyService: IMyService{
   
     public void GetMyUsers(){
         //****Do something here *****
     }
}

Step3: Next we register MyService in the ConfigureServices method of the Startup class. We do this by using one of the three methods services.AddTransient, services.AddScoped and services.AddSingleton provided by IServiceCollection. For more information on these methods and the lifetime of the registered services see Service lifetimes below.


public class Startup{


    public IConfiguration Configuration { get; }



    public Startup(IConfiguration configuration)

    {

        Configuration = configuration;
    }


    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyServiceMyService>();      
    }
}


Step4: In your controller class you can inject MyService in the constructor and use it like below. 


 public class MyController : ControllerBase{

        private IMyService _myService;  

        public MyController(MyService _myService)
        {
            _myService = myService;
        }


        [HttpGet]
        [Route("/api/user")]
        public IActionResult Get()
        {
            _myService.GetMyUsers();
        }
 }

Using Service Extensions


You can call write your own service extensions services.Add{SERVICE_NAME} by extending the ServicesConfiguration class like below.



public static class ServicesConfiguration{


        public static void AddMyService(this IServiceCollection     services)

        {

            services.AddScoped<IMyServiceMyService>();      

        }

}


You can then use it in the Startup class like below.


public class Startup{


    public IConfiguration Configuration { get; }



    public Startup(IConfiguration configuration)

    {

        Configuration = configuration;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IMyServiceMyService>();      
    }
}


Service lifetimes


Transient

This is probably the default choice, its best suited for lightweight and stateless services. You can use this method in applications that don't implement a request-response pattern.

Scoped

This is best suited for web applications as it is created once per client request.


Singleton

This is created once for the life of the application. There is only one instance of this service. 



No comments: