To get the obvious out of the way, there is no harm in doing a null check in your constructor.
There are two methods for obtaining DI services from the framework.
The first is GetService<T>()
. This will return a null value if such a service has not been registered.
The second is GetRequiredService<T>()
. This will throw an exception if the service can't be found.
Both of these methods throw exceptions if they can't fully instantiate the service you are asking for.
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection()
.AddTransient<IServiceB, ServiceB>()
.BuildServiceProvider();
var servB = services.GetService<IServiceB>();
}
}
public interface IServiceA { }
public interface IServiceB { }
public class ServiceA : IServiceA { }
public class ServiceB : IServiceB { public ServiceB(IServiceA a) { } }
In this example, ServiceB
requires an IServiceA
, but A
is not added to the dependency graph. The last method will throw an exception:
System.InvalidOperationException: 'Unable to resolve service for type 'DITests.IServiceA' while attempting to activate 'DITests.ServiceB'.'
If I instead did services.GetService<IServiceA>()
, I'd get a null value.
You can see this for yourself by looking at the GitHub source code. When calling either method, it will eventually make it's way to the CreateConstructorCallSite
method. This throws an exception if it's unable to resolve the dependencies of your type.
As for ASP.Net Core MVC, it uses GetRequiredService<>()
for getting your controllers from the DI graph.
In conclusion, no, you do not need to perform null checks for DI objects in your constructor if you're using the pure Microsoft DI framework. As Camilo Terevinto said, the framework does not allow it.
As noted in your post, I have not seen a written Microsoft document that explicitly says you do not need to
If you are passing in an IServiceProvider
as a constructor argument and you're resolving services from within the constructor, then you'll need to do null checks.
... manual instantiation would never make it through code reviews and common sense
even in unit tests? – Preteritive