Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can ASP.NET core dependency injection inject null references?

In my job we are developing ASP.NET core applications. I keep seeing the follwing pattern used with dependency-injection. In this example Logic depends on OtherLogic:

public class Logic {
    private readonly OtherLogic myOtherLogic;

    public Logic(OtherLogic myOtherLogic) {
        // I mean specifically this pattern of checking injected dependencies for null:
        this.myOtherLogic = myOtherLogic
            ?? throw new ArgumentNullException(nameof(myOtherLogic));
    }
}

All dependencies are added to an IServiceCollection during service configuration and both (Logic and OtherLogic) are only retrieved from dependency injection. In my current project I’m using DotNet 5 and I have enabled nullable reference types if that matters.

I’d like to drop this Guard Clause pattern, because I believe the injector will always throw an exception (during service configuration) when it’s unable to resolve a non-optional service.
My question is, in which circumstances the injector could inject a null-reference for a non-optional service? Is it even possible?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This article doesn’t mention the possibility of null being injected, but as far as I can see, also doesn’t explicitly deny it. Just want to make sure I don’t run into trouble later on, thanks for your time 🙂

>Solution :

Under ‘normal’ conditions (i.e. when solely depending on the use of Auto-Wiring) null values can’t be injected. The following code snippets, however, show examples of when null references can be injected into Logic:

Case 1: Manual construction

new Logic(null);

Case 2: Manual construction using factory registration

services.AddTransient(c => new Logic(null));

Case 3: Direct null injection through factory registration

services.AddTransient(c => new Logic(null));

Case 4: Incorrect use of GetService opposed to GetRequiredService in factory

services.AddTransient(c => new Logic(c.GetService<OtherLogic>()));

Case 5: Auto-registration with dependency that returns null from its factory registration

services.AddTransient<Logic>();
services.AddTransient<OtherLogic>(c => null);

In my opinion, option 5 should not be allowed, and I consider it a design flow in MS.DI to allow a factory registration to return null. But that still leaves the other three cases where the Logic constructor is called using plain-old C#.

Whether or not you want to be very safe and protect the class’s pre conditions using a Guard Clause is up to you. Personally, for applications where I make use of a DI Container that doesn’t allow case 5 and makes it hard to do case 4, I typically leave out the Guard Clauses. This even allows me to use the more concise record syntax:

public sealed record Logic(OtherLogic MyOtherLogic)
{
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading