Best Practice: How to get several dependency repositories into a ActionController?
I have a InventoryController that gets a IInventoryRepository inyected, however my needs have changed, and now one of the controllers methods also needs to use another 2 repositories, ILoansRepository (to see the get info about loaned inventory items) and another one, where some stats and extra info are found.
The way it works is that a ViewModelBuilder class that gets called from an ActionMethod in the InventoryController, that is the one that actually needs those. Curren开发者_如何学JAVAtly I was passing the IInventoryRepository from the controller to the builder, but how should I do it now? Should I get the 3 repositories injected into the controller, and then pass them to the builder, just as I've been doing now? Or should I just do a IoC.GetInstance()? (although I think that is an anti-pattern isnt it?)
thanks!
In situations like these, the following guidelines come into play:
- Too many dependencies is a smell that you violate the Single Responsibility Principle.
- Don't have more than four dependencies. This is a relative guideline. I personally strive to have less; I get restless as soon as I add a third dependency (see the first item above), but can live with up to four. More than that and I have to refactor.
- Don't take dependencies just to pass them on.
As far as I can tell, with three dependencies, you are still more or less within the safety zone when it comes to the number of dependencies, although you should start watching that particular design aspect more carefully.
However, as I understand your current implementation, you simply pass on the dependencies to a ViewModelBuilder (thus violating the third bullet). A slightly better option would be to define an abstraction of that (say, IViewModelBuilder) and inject that into the controller instead of all three repositories.
Under no circumstance should you resort to the Service Locator anti-pattern (IoC.GetInstance()).
To much responsibility for controller.
Maybe you should create a special service to handle that and that service should use those repositories (through IoC) auto-wired by constructor.
If your controller does too much work, split it into several ones.
If you inject 3 repositories just to create ViewModelBinder, don't: inject (I)ViewModelBinder instead. Let IoC container do its job and resolve the dependencies for you; moreover, this will simplify the architecture, the testing, etc.
Using ServiceLocator / GetInstance isn't always avoidable; sometimes you don't have "root" injection point like MVC controller factory and can't control object creation - for example, of model binders. So, I let my model binders (not builders) call GetInstance but I make my own "root": for example, they call GetInstance<IModelResolver>, not GetInstance<Entity>.
精彩评论