How To Add Dependency Injection In Your Sitecore Application

What is Dependency Injection?

 
Dependency Injection is a software design pattern that will allow developers to develop loosely coupled codes between two components. It allows better management for future changes.
 
Along with better management, it allows for a better unit testing process and increases code reusability and maintainability.
 
There are a few ways of implementing DI.
  1. Constructor Injection
    This injector supplies the dependency through the constructor of the class. 

  2. Property Injection
    Injector supplies dependency through the setter of the property of the class. As this is being done through Setter, this also called Setter Injections.

  3. Method Injection
    Over here client class implements an interface that declares the method to supply the dependency and using this interface the injector supplies the dependency to the client class.
In Sitecore, we will design with constructor injection.
 
To start off, create your project (either Foundation or Feature) in Solution.
 
Create a new interface and write down the methods you need. After that, add your concrete class and implement the interface.
 
Let’s say we are working on the article section of a project and this a feature of articles and we need a repository to save articles.
 
Model
  1. namespace Feature.Articles.Models  
  2. {  
  3.     public class Article  
  4.     {  
  5.         public string Subject { getset; }  
  6.         public string Body { getset; }  
  7.         public List<string> AttachementList { getset; }  
  8.         public string Username { getset; }  
  9.         public List<string> Tags { getset; }  
  10.     }  
  11. }  
Interface
  1. public interface ISaveArticleReository  
  2. {  
  3.     bool SaveArticle(Article article);  
  4. }  
Class
  1. public class SaveArticleRepository : ISaveArticleReository  
  2. {  
  3.     public bool SaveArticleInSQLServer (Article article)  
  4.     {  
  5.         // do your code for saving in SQL Server  
  6.     }  
  7. }  
  8.   
  9. public class SaveArticleRepository : ISaveArticleReository  
  10. {  
  11.     public bool SaveArticleInMongoDB (Article article)  
  12.     {  
  13.         // do your code for saving in Mongo DB  
  14.     }  
  15. }  
Set up the connection between Interface and class.
 
You need to connect both the class and interface in the RegisterDependencies class. For the same, create a folder name DependencyInjection and create a class. Make sure the class is implemented from the interface. ISaveArticleReository. 
 
Within the configure method, connect the class to interface using among three methods.
  • AddTransient<TService, TImplementation>() - Transient objects are always different; a new instance is provided to every controller and every service.
  • AddScoped<TService, TImplementation>() - Scoped objects are the same within a request, but different across different requests.
  • AddSingleton<TService, TImplementation>() - Singleton objects are the same for every object and every request.
For more please visit .NET documentation.
  1. namespace Feature.Articles.DependenyInjection    
  2. {    
  3.     public class RegisterDependencies : IServicesConfigurator    
  4.     {    
  5.         public void Configure(IServiceCollection serviceCollection)    
  6.         {    
  7.             serviceCollection.AddTransient<ISaveArticleReository, SaveArticleInSQLServer>();    
  8.             //serviceCollection.AddTransient<ISaveArticleReository, SaveArticleInMongoDB>();     
  9.             // Switch the concrete class name as per your need.    
  10.         }    
  11.     }    
  12. }    
Note
We have two concrete classes from one interface, one is saving the data into SQL server and another one in MongoDB with two different implementations. Switch the concrete class in the dependency injections to switch between implementations.
 
After this, you need to register the Dependency Injection class RegisterDependencies.
 
Creating the RegisterDependencies class is not enough to enable the Dependency injection is Sitecore, you have to identify the Sitecore engine using a patch config file.
 
Create a config file in App Config folder. Location should be like App_Config -> Include -> <Fature/Foundation> -> <CompoenentName>.Config
 
Add the below lines into the file. 
  1. <?xml version="1.0"?>    
  2. <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">    
  3.   <sitecore>    
  4.     <services>    
  5.       <configurator type="<Namespace>.<Class Name>, <Project Name>" />    
  6.     </services>    
  7.   </sitecore>    
  8. </configuration>   
As per our solution the config file will be like,
  1. <?xml version="1.0"?>    
  2. <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">    
  3.   <sitecore>    
  4.     <services>    
  5.       <configurator type="Feature.Articles.DependenyInjection.RegisterDependencies, Feature.Articles" />    
  6.     </services>    
  7.   </sitecore>    
  8. </configuration>     
After then we have to inject the Interface into controller file. For the same create a readonly private variant of interface type in the controller.
  1. namespace Feature.Articles.Controllers  
  2. {  
  3.     public class ArticleCommentAPIController : SitecoreController  
  4.     {  
  5.        private readonly ISaveArticleReository _saveArticleReository;   
  6.   
  7.        public ArticleCommentAPIController(ISaveArticleReository saveArticleReository) => _saveArticleReository = saveArticleReository;  
  8.   
  9.        public JsonResult SaveArticle (Article article)  
  10.        {  
  11.           return Json(saveArticleReository.SaveArticle(article);  
  12.        }  
  13.     }  
  14. }  
Now build your project and upload the DLL and Config file to test.