Decorator Pattern with Dependency Injection in .NET Core
Today’s Highlight Video :
Refit client is an automatic type-safe REST library for .NET Core, Xamarin and .NET
Watch this video about How to Use Refit Client library in .NET API via two different approaches.
Decorator is a structural design pattern that lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.
If you’re interested in exploring this pattern further, I recommend referring to the Gang of Four book. In today’s newsletter, my primary focus is demonstrating how to showcase its functionality through dependency injection.
Use cases of Decorator Pattern
We can use decorator pattern when we have to introduce a new behavior to existing code base for example
-
Extra Logging
-
Build Resiliency
And we want it to apply on all instances.
What is Dependency Injection (DI)
Dependency injection involves providing a class with its required dependencies from an external source rather than having the class create them itself.
This helps to decouple the object creation process from the caller, leading to a more modular and flexible system.
In other words, it allows a class to focus on its core functionality rather than worrying about how to create and manage its dependencies.
âś… In .NET 6 and onwards we can implement DI in Program.cs class by using builder.Services
✅ For previous versions of .NET, to implement DI we need to add the service in “ConfigureServices” method which is in Startup.cs file.
How does DI fits with Decorator Pattern?
Recently I was working in a Unit Test project where one of my class was taking a OptionsModel but it was not from IOptions/IConfiguration.
We can say class name was StudentService and it was implementing IStudentService. So first thing that comes to mind about registering its dependency was simple by adding this line :
builder.Services.AddScoped<IStudentService, StudentService>();
But this could have created the issue because class was taking a model, so I leveraged the decorator pattern here in this way :
builder.Services.AddScoped<IStudentService>(sp =>
{
var studentOptions = sp.
GetRequiredService<IOptionsSnapshot<StudentOptions>>().Value;
var studentService = new StudentService(studentOptions);
return studentService;
});
That is how we have successfully resolved the dependency problem.
But is it perfect solution ?
Answer is no, when the parameter changes we need to update the instance but until then it will be alright.
Maybe the example does not seem relevant to you but I was trying to point out towards the pattern here.
If you want more efficient solution than this then you should consider the Scrutor Nuget Package, I will try to cover it in upcoming newsletters.
Whenever you're ready, there are 3 ways I can help you:
- Subscribe to my youtube channel : For in-depth tutorials, coding tips, and industry insights.
- Promote yourself to 9,000+ subscribers : By sponsoring this newsletter
- Patreon community : Get access to all of my blogs and articles at one place