The benefits and correct usage of a DI Container

601 views Asked by At

I'm having troubles getting the advantage of a IoC (DI) container like Ninject, Unity or whatever. I understand the concepts as follows:

  • DI: Injecting a dependency into the class that requires it (preferably via constructor injection). I totally see why the less tight coupling is a good thing.

    public MyClass{
        ISomeService svc;  
    
        public MyClass(ISomeService svc){
            svc = svc;
        }
    
        public doSomething(){
            svc.doSomething();
        }
    }
    
  • Service Locator: When a "container" is used directly inside the class that requires a dependancy, to resolve the dependancy. I do get the point that this generates another dependancy and I also see that basically nothing is getting injected.

    public MyClass{                 
        public MyClass(){}
    
        public doSomething(){
            ServiceLocator.resolve<ISomeService>().doSomething();
        }
    }
    

Now, what confuses me is the concept of a "DI container". To me, it looks exactly like a service locator which - as far as I read - should only be used in the entry point / startup method of an application to register and resolve the dependancies and inject them into the constructors of other classes - and not within a concrete class that needs the dependancy (probably for the same reason why Service locators are considered "bad")

  • What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?

    public void main(){                 
        DIContainer.register<ISomeService>(new SomeService());
        // ...
    
        var myclass = new MyClass(DIContainer.resolve<ISomeService>());
        myclass.doSomething();
    }
    
  • Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?

1

There are 1 answers

0
Yacoub Massad On

What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?

DI containers are supposed to help you create an object graph quickly. You just tell it which concrete implementations you want to use for which abstractions (the registration phase), and then it can create any objects you want want (resolve phase).

If you create the dependencies and pass them to the constructor (in the application initialization code), then you are actually doing Pure DI.

I would argue that Pure DI is a better approach in many cases. See my article here

Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?

I would say yes. You should create the object graph when your application starts up. This is called the composition root.

If you need to create objects after your application has started then you should use factories (mainly abstract factories). And such factories will be created with the other objects in the composition roots.

Your classes shouldn't do much in the constructor, this will make the cost of creating all the dependencies at the composition root low.

However, I would say that it is OK to create some types of objects using the new keyword in special cases. Like when the object is a simple Data Transfer Object (DTO)