Let’s say I register a scoped service to my ASP.NET 6 web application in Program.cs
:
services.AddScoped<MyRequestService>();
Now let’s say I have some custom middleware that runs after MVC routing:
app.UseRouting();
app.Use(async delegate (HttpContext Context, Func<Task> Next)
{
await Next(); // <-- here a controller gets instantiated based on MVC routing
// and *MIGHT* have 'MyRequestService' injected, but
// it's *NOT GUARANTEED*
// what do I put here to check if 'MyRequestService' was injected into the
// controller that was chosen by MVC?
});
Now, after the call to await Next()
in the middleware, I would like to check if MyRequestService
was used by the controller that was chosen by MVC. How can I do this?
I cannot use Context.RequestServices.GetRequiredService<MyRequestService>()
since that will just instantiate the service if it isn’t already instantiated. I need to check if the controller injected it, without inadvertently instantiating it.
3
Answers
I used reflection per Jonesopolis's suggestion in the comments, but instead of using reflection on controllers, I'm using it to get at the internal dependency injection object cache. I'm caching the ResolvedServices
PropertyInfo
using aLazy<PropertyInfo>
object. This works, but I don't like it. Hopefully ASP.NET will have a public accessor for this soon:This is what I would do, it is not tested but I think this concept should work and it is easier to read than reflexion in my opinion:
Instead of trying to scan the DI container by reflection, I would try to use the
HttpContext
class. It has properties likeFeatures
andItems
. Both are able to hold arbitrary data within the scope of the current context. Your service could for example add an entry with a specific key (e.g. a const string) into theItems
dictionary with any data needed within the value and in your middleware you check after the return ofNext()
if the dictionary contains the specified key. If yes, your service was used.In that case the default mechanism of ASP is used and no reflection is needed.