Why we need framework to do the Dependency Resolver?

In that case your ProductsController still depends on a low level component (the concrete ProductRepository in your case) which is a violation of the Dependency Inversion Principle. Whether or not this is a problem depends on multiple factors, but it causes the following problems:

  • The creation of the ProductRepository is still duplicated throughout the application causing you to make sweeping changes throughout the application when the constructor of ProductRepository chances (assuming that ProductRepository is used in more places, which is quite reasonable) which would be an Open/Closed Principle violation.
  • It causes you to make sweeping changes whenever you decide to wrap this ProductService with a decorator or interceptor that adds cross-cutting concerns (such as logging, audit trailing, security filtering, etc) that you surely don't want to repeat that code throughout all your repositories (again an OCP violation).
  • It forces the ProductsController to know about the ProductsRepository, which might be a problem depending on the size and complexity of the application your are writing.

So this is not about the use of frameworks, it's about applying software design principles. If you decide to adhere to these principles to make your application more maintainable, the frameworks like Ninject, Autofac and Simple Injector can help you with making the startup path of your application more maintainable. But nothing is preventing you from applying these principles without the use of any tool or library.


Small disclaimer: I'm an avid Unity user, and here are my 2 cents.

1st: Violation of SOLID (SRP/OCP/DIP)

Already stated by @democodemonkey and @thumbmunkeys, you couple the 2 classes tightly. Let's say that some classes (let it be ProductsThingamajigOne and ProductsThingamajigTwo) are using the ProductsController, and are using its default constructor. What if in the architect decides that the system should not use a ProductsRepository that saves Products into files, but should use a database or a cloud storage. What would the impact be on the classes?

2nd: What if the ProductRepository needs another dependency?

If the repository is based on a database, you might need to provide it with a ConnectionString. If it's based on files, you might need to provide it with a class of settings providing the exact path of where to save the files - and the truth is, that in general, applications tend to contain dependency trees (A dependent on B and C, B dependent on D, C dependent on E, D dependent on F and G and so on) that have more then 2 levels, so the SOLID violations hurts more, as more code has to be changed to perform some task - but even before that, can you imagine the code that would create the whole app? Fact is, classes can have many dependencies of theirs own - and in this case, the issues described earlier multiply.

That's usually the job of the Bootstrapper - it defines the dependency structure, and performs (usually) a single resolve that brings the whole system up, like a puppet on a string.

3rd: What if the Dependency-Tree is not a tree, but a Graph?

Consider the following case: Class A dependent on classes B and C, B and C both are dependent on class D, and are expecting to use the same instance of D. A common practice was to make D a singleton, but that could cause a lot of issues. The other option is to pass an instance of D into the constructor of A, and have it create B and C, or pass instances of B and C to A and create them outside - and the complexity goes on and on.

4th: Packing (Assemblies)

Your code assumes that 'ProductsController' can see 'ProductRepository' (assembly-wise). What if there's no reference between them? the Assembly Map can be non-trivial. usually, the bootstrapping code (I'm assuming that it's in code and not in configuration file for a second here) is written in an assembly that references the entire solution. (This was also described by @Steven).

5th: Cool stuff you can do with IoC containers

Singletons are made easy (with unity: simply use a 'containercontrolledlifetimemanager' when registering), Lazy Instantiation made really easy (with unity: register mapping of and ask in the constructor for a Func). Those are just a couple of examples of things that IoC containers give you for (almost) free.


Of course you could do that, but this would cause the following issues:

  • The dependency to IProductRepository is not explicit anymore, it looks like an optional dependency
  • Other parts of the code might instantiate a different implementation of IProductRepository, which would be probably a problem in this case
  • The class becomes tightly coupled to ProductsController as it internally creates a dependency

In my opinion this is not a question about a framework. The point is to make modules composable, by exposing their dependencies in a constructor or property. Your example somewhat obfuscates that.