I am doing this project at home in ASP.NET Core where I have a few projects – Core, Services, Infrastructure and Web that I combine in a single assembly. That’s an attempt of the so called Onion Architecture I started implementing.
In my Services project I have a photo uploader that needs access to the current environment in order for it to work.
Before I started refactoring that class resided in the Web where I just used the built-in dependency to add IHostingEnvironment in the PhotoUploader.cs.
After I started refactoring and moved the class inside the Services project (which is just a simple library) I had to find another way to send the current environment upon creation using the DI.
Here is the class I am putting into DI
public class PhotoUploader : IPhotoUploader
{
private readonly IHostingEnvironment _env;
public PhotoUploader(IHostingEnvironment env)
{
_env = env;
}
}
As you see, we need IHostingEnvironment upon initialization.
To do that, in the Startup.cs in my Web project I did the following
First of all, I added IHostingEnvironment as a DI in the Startup.cs constructor.
private readonly IHostingEnvironment _env;
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
Configuration = configuration;
_env = env;
}
Then I simply added my PhotoUploader to the DI with _env as parameter:
services.AddSingleton<IPhotoUploader>(new PhotoUploader(_env));
That’s it. Now when .NET Core CLR initializes the class via DI it will automatically put the IHostingEnvironment as parameter inside the Services project’s PhotoUploader.
Happy coding, folks!
Hi,
This is a really neat example of DI. There are just a few improvements that you can make.
First IHostingEnvironment is wired up under the hood by the web builder in Program.cs so we do not need to call it again in the Startup unless we need to do some config/service wiring depending on the environment.
Also, there is an generic override which accepts the interface and the implementation IServiceCollection AddSingleton(this IServiceCollection services).
Having this we can simplify registration like this https://gist.github.com/VladislavMS/394649cd4370c08bacba9b2e098d2739 .
Secondly, it’s usually a more viable solution to the service to use options instead of passing the hosting environment.
In this way you can load settings for the service through appsetting.json or appsettings.{Environment}.json (if it exists).
You can directly use Configure(this IServiceCollection services, IConfiguration config) extension method or Configure(this IServiceCollection services, Action configureOptions) to do some chekky and complicating options setup.
https://gist.github.com/VladislavMS/b4daeda7a4d8b1194e06c48d929ac606
Good work. Keep it up 🙂
Thank you so much for the amazing explanation, Vladislav! Great job!
I definitely have a lot to learn, lol.