Your 'Global' approach is more or less a Poor Man's Service Locator. Many people, including me, consider Service Locator an anti-pattern.
The main reason for that is that its usage is implicit; it is hidden from the consumer, so a developer writing client code will probably not be aware that it exists.
As a client developer, I could easily write this code:
var a = new A();
and then just start partying on a
straight away. If A depends on IService, methods invoked on the instance are likely to throw exceptions if Config.Service was never set, and there is no guarantee that this ever happened.
On the other hand, when you use Constructor Injection, you can more or less guarantee that the IService instance is being injected. Now this code will not compile:
var a = new A();
so it forces client developers to supply an instance of IService. Obviously client developers could simply supply null:
var a = new A(null);
but you could easily fix this with a Guard Clause.
class A
{
public A(IService service)
{
if(service == null)
{
throw new ArgumentNullException();
}
_service = service;
}
}
This guarantees that the service instance is valid, particularly if you combine it by making the _service
field readonly
.
Whether or not you use a DI Container to resolve dependencies is a perpendicular matter.
There are, in my opinion, no advantages of using a Service Locator over Constructor Injection.