Take advantage of the dependency injection principle to provide support for pluggable implementations in your application and build loosely coupled, testable components The Dependency Inversion Principle states that the high level modules in an application should not depend on the low level modules; both should rather depend on abstractions. Both inversion of control and dependency injection are ways that enable you to break the dependencies between the components in your application. The IOC design pattern states that objects should not create objects on which they depend to perform some activity. As an example, you would typically have a business layer and a core or framework layer in your application. The business layer code should invoke the framework layer code. Using the IOC principle, this can be inverted, i.e., the framework layer would call the business layer. The IOC containers helps you in automatic instantiation and life cycle management of the objects. Some examples of popular IOC containers include Castle Windsor and Structure Map. Dependency injection Dependency injection is a subset of the Inversion of Control (IoC) principle. The DI principle is a technique that is used to remove internal dependencies from the implementation by enabling these dependencies to be injected externally. It states that when an object is dependent on other objects, such objects should be created using a separate framework or component. The IOC containers take advantage of dependency injection to invert the flow of control and provide the necessary implementation or the dependent code. In essence, while IoC is the ability of varying the implementation of a contract, DI is the ability to provide the necessary implementation when asked for. In other words, Dependency Injection is a realization of the Inversion of Control (IoC) principle. Martin Fowler has a great article on IoC and DI. There are basically three types of dependency injection: constructor injection, setter injection, and interface injection. While constructor injection uses a constructor to inject the dependencies, setter injection take advantage of setter properties to inject the object dependencies. The following code snippet illustrates how constructor injection is used. public class BusinessLogic { public BusinessLogic(BusinessEntity entity) { this.BusinessEntity = entity; } } Note how the dependency is passed using the constructor of the BusinessLogic class. interface injection uses interfaces to inject the dependencies. Implementing interface injection In this section we would implement dependency injection using interfaces, i.e., using the interface injection technique. The following code snippet shows three classes: EntityBase, Employee, and Customer. EntityBase is the base of both the entity classes Employee and Customer. public abstract class EntityBase { public Int32 ID { get; private set; } } public class Employee : EntityBase { //TODO: Properties that correspond to the Employee entity } public class Customer : EntityBase { //TODO: Properties that correspond to the Customer entity } Now, refer to the following interfaces. The ICustomerRepository and IEmployeeRepository interfaces inherit the IRepository interface — IRepository is the base interface here and declares a few repository methods. public interface IRepository { IQueryable<EntityBase> GetAll(); void Add(EntityBase entity); void Delete(EntityBase entity); void Edit(EntityBase entity); void Save(); } public interface ICustomerRepository : IRepository { Customer GetSingle(int customerId); } public interface IEmployeeRepository : IRepository { Employee GetSingle(int employeeId); } Note that the GetSingle method is specific to the ICustomerRepository and IEmployeeRepository interfaces. Now that the interfaces are in place, let’s create the concrete classes to perform CRUD operations for both the Customer and Employee entities. The following code snippet shows how the EmployeeRepository and CustomerRepository classes look like. Note that both these classes implement the IEmployeeRepository and ICustomerRepository interfaces respectively. public class EmployeeRepository :IEmployeeRepository { public Employee GetSingle(int employeeId) { throw new System.NotImplementedException(); } public IQueryable<EntityBase> GetAll() { throw new System.NotImplementedException(); } public void Add(EntityBase entity) { //Some code } public void Delete(EntityBase entity) { //Some code } public void Edit(EntityBase entity) { //Some code } public void Save() { //Some code } } public class CustomerRepository : ICustomerRepository { public Customer GetSingle(int customerId) { throw new System.NotImplementedException(); } public IQueryable<EntityBase> GetAll() { throw new System.NotImplementedException(); } public void Add(EntityBase entity) { throw new System.NotImplementedException(); } public void Delete(EntityBase entity) { throw new System.NotImplementedException(); } public void Edit(EntityBase entity) { throw new System.NotImplementedException(); } public void Save() { throw new System.NotImplementedException(); } } The following class represents the BusinessLogic class. Note that this is generic in nature and you would need to extend this class if need be to provide some specific implementation. For the sake of this illustration, this class contains just one property named Repository of type IRepository. public class BusinessLogic { public IRepository Repository { get; set; } } And, you are done! The following code snippet illustrates how the Add method of the EmployeeRepository class can be invoked. Note how the repository instance is injected using interface injection technique. static void Main(string[] args) { Employee emp = new Employee(); IEmployeeRepository repository = new EmployeeRepository(); BusinessLogic blObject = new BusinessLogic(); blObject.Repository = repository; blObject.Repository.Add(emp); } Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos