Dependency Injection(DI) Design Pattern
What is Dependency Injection (DI) Design Pattern?
Dependency Injection (DI) is a design pattern that allows you to remove the hard-coded dependencies between objects in your application, and instead, provide them with their dependencies through a central location. This makes it easier to change the dependencies of an object without affecting the rest of the application, and also makes it easier to test your application by providing mock dependencies in a test environment.
" Dependency injection is the practice of providing dependent objects for a class from outside rather than the class creating it. So, in simple words, the object creation process is isolated from the caller. This helps to create a proper decoupled system."
Why do we need the Dependency Injection Design Pattern in application development?
Dependency injection is a design pattern that allows a class to receive its dependencies from an external source, rather than creating them internally. This makes the class more flexible and easier to test, as its dependencies can be easily swapped out for mock objects during testing. In C#, dependency injection can be implemented using a variety of libraries, such as Microsoft's Unity or Autofac. These libraries provide a way to configure and manage dependencies, making it easier to implement the dependency injection pattern in your code. we can say that Dependency Injection Design Pattern is used to reduce the tight coupling between the software components. As a result, we can easily manage future changes and other complexity in our application.
"By using DI classes are decoupled from each other so you make changes at one place its reflected all over the places."
Merits of dependency injection
Demerits of dependency injection
Though dependency injection comes a long way in writing loosely coupled and easily maintained code, critics argue that:
Explain Different Types of Dependency Injection ?
There are several types of dependency injection that can be implemented in C#:
1. Implementing Constructor Injection via c# .
Property injection is a way to provide dependencies to a class by setting them through a public property on the class. Here is an example of how property injection can be implemented in C#:
interface IDatabase {
?void Connect();
}
public class SqlServerDatabase : IDatabase {
?public void Connect() {
???// Connect to SQL Server
?}
}
class MyClass {
?private IDatabase _database;
?public MyClass(IDatabase database) {
???_database = database;
?}
?public void DoSomething() {
???_database.Connect();
???// Perform some action
?}
}
In this example, MyClass has a public property Database of type IDatabase, which is used to provide the dependency. The specific implementation of the IDatabase interface (e.g SqlServerDatabase) can be set on the MyClass object after it is created, which makes the class more flexible and easier to test.
You can use a Dependency Injection Container such as Autofac, Ninject, or Unity to handle the instantiation of the objects and the injection of the dependencies.
public class Program {
?static void Main(string[] args) {
???IDatabase db = new SqlServerDatabase();
???MyClass obj = new MyClass(db);
???obj.DoSomething();
?}
}
You can also use a Dependency Injection Container to handle the instantiation of the objects and the injection of the dependencies.
public class Program {
?static void Main(string[] args) {
???var builder = new ContainerBuilder();
???builder.RegisterType<SqlServerDatabase>().As<IDatabase>();
???builder.RegisterType<MyClass>();
???var container = builder.Build();
???var obj = container.Resolve<MyClass>();
???obj.DoSomething();
?}
}
This way, you can decouple the class from the concrete implementation of the dependency, making it more flexible and easier to test.
Advantages of Constructor Dependency Injection :
2. Implementing Property Injection ?
Property injection is a way to provide dependencies to a class by setting them through a public property on the class. Here is an example of how property injection can be implemented in C#:
interface IDatabase {
?void Connect();
}
class SqlServerDatabase : IDatabase {
?public void Connect() {
???// Connect to SQL Server
?}
}
class MyClass {
领英推荐
?public IDatabase Database { get; set; }
?public void DoSomething() {
???Database.Connect();
???// Perform some action
?}
}
In this example, MyClass has a public property Database of type IDatabase, which is used to provide the dependency. The specific implementation of the IDatabase interface (e.g SqlServerDatabase) can be set on the MyClass object after it is created, which makes the class more flexible and easier to test.
You can use a Dependency Injection Container such as Autofac, Ninject, or Unity to handle the instantiation of the objects and the injection of the dependencies.
public class Program {
?static void Main(string[] args) {
???var builder = new ContainerBuilder();
???builder.RegisterType<SqlServerDatabase>().As<IDatabase>();
???builder.RegisterType<MyClass>();
???var container = builder.Build();
???var obj = container.Resolve<MyClass>();
???obj.Database = container.Resolve<IDatabase>();
???obj.DoSomething();
?}
}
Alternatively, you can set the property directly like this:
public class Program {
?static void Main(string[] args) {
???IDatabase db = new SqlServerDatabase();
???MyClass obj = new MyClass();
???obj.Database = db;
???obj.DoSomething();
?}
}
It's important to note that Property Injection is less common than Constructor Injection and it could be considered as less maintainable as it's harder to understand the dependencies of a class. Some developers also consider Property Injection as an anti-pattern as it can lead to tight coupling between classes.
3. Implementing Method Injection via c# .
Method injection is a way to provide dependencies to a class by passing them in as arguments to a method. Here is an example of how method injection can be implemented in C#:
interface IDatabase {
?void Connect();
}
public class SqlServerDatabase : IDatabase {
?public void Connect() {
???// Connect to SQL Server
?}
}
class MyClass {
?public void DoSomething(IDatabase database) {
???database.Connect();
???// Perform some action
?}
}
In this example, MyClass's DoSomething method has a parameter of type IDatabase which is used to provide the dependency. The specific implementation of the IDatabase interface (e.g SqlServerDatabase) can be passed in as an argument when the DoSomething method is called, which makes the class more flexible and easier to test.
You can use a Dependency Injection Container such as Autofac, Ninject, or Unity to handle the instantiation of the objects and the injection of the dependencies.
public class Program {
?static void Main(string[] args) {
???var builder = new ContainerBuilder();
???builder.RegisterType<SqlServerDatabase>().As<IDatabase>();
???builder.RegisterType<MyClass>();
???var container = builder.Build();
???var obj = container.Resolve<MyClass>();
???var db = container.Resolve<IDatabase>();
???obj.DoSomething(db);
?}
}
Alternatively, you can pass the dependency directly like this:
class Program {
?static void Main(string[] args) {
???IDatabase db = new SqlServerDatabase();
???MyClass obj = new MyClass();
???obj.DoSomething(db);
?}
}
Method injection is less common than Constructor Injection, it's considered more appropriate for scenarios where a single method requires multiple dependencies or when you need to pass dependencies to a class that cannot be modified.
It's important to note that Method injection is less common than Constructor Injection and it could be considered as less maintainable as it's harder to understand the dependencies of a class and it could lead to tight coupling between classes.