I am new to C # / ASP, coming from the Java world. I read this article: https://docs.asp.net/en/latest/fundamentals/dependency-injection.html#service-lifetimes-and-registration-options , which wisely warns about the dangers associated with dependency injection with a smaller scope . Unfortunately, this does not explain how to solve this problem in C # / ASP. There is a concept of provider in Java
interface Provider<T> { T get(); }
which, among other things, helps to solve the survey problem: whenever the binding for some type T is a register, we can enter an automatically generated instance of Provider <T> instead of T, and then get an instance of T when necessary: ββthe automatically created Provider guarantees so that we get an instance suitable for the current scope (regardless of this scope: HTTP request, HTTP session, or other custom scopes). The standard DI framework built into the ASP.NET core has nothing of the kind, but I thought it should be very easy to implement in C #, since C # generators don't suck like java do ( https: // docs. oracle.com/javase/tutorial/java/generics/erasure.html ). So I created the following class:
public class Provider<T>: IProvider<T> { private readonly IServiceProvider serviceProvider; public Provider(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } public T IProvider<T>.Get() { return serviceProvider.GetService<T>(); } }
and I tried using it like this:
public class SingletonService : ISingletonService { private readonly IProvider<IScopedService> scopedServiceProvider; public SingletonService(IProvider<IScopedService> scopedServiceProvider) { this.scopedServiceProvider = scopedServiceProvider; } public string PerformMyTask() { var scopedDependency = scopedServiceProvider.Get();
and in my Startup class:
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<ISingletonService, SingletonService>(); services.AddScoped<IScopedService, ScopedService>(); services.AddTransient<IProvider<IScopedService>, Provider<IScopedService>>();
Unfortunately, this does not work as I expected, since the IServiceProvider instance also seems to be bound to the current HTTP request, and I get the exact same ScopedDependency instance from my provider during processing of various requests: (
Any clues how can I solve this problem? Perhaps there is some kind of object of a higher level than the ServiceProvider, tied to approximately the life cycle of the application (and not to the current request), which creates instances of objects with the request area (or the ServiceProvider itself), which I can insert into the objects of my provider instead ServiceProvider? For example, in Java, if I use google Guice as the DI framework, there is an Injector object, usually created when the application starts, which contains all the type bindings and has a method
<T> T getInstance(Class<T> type);
which checks the current scope and returns the corresponding instance.
change
I think one of the possible ways to do this would be to get a new reference to the ServiceProvider instance every time in the Proivder <T> .Get () method instead of typing it into the constructor and storing var as an instance. Thus, my components will still not be polluted by a reference to the platform-specific IServiceProvider, since it will be hidden from them in the Provider <T> implementation, which they access through the IProvider <T> abstract interface. However, I can not find on the Internet if you can get such a link from the Provider class and how to do it. Any pointers in this direction would be appreciated :)
Thanks!