I noticed that some people don’t use their IoC-Container in the manner they should to. They inject the container into their objects like this:
1: public class Foo : IFoo
2: {
3: private IContainer _container;
4:
5: public Foo(IContainer container) {
6: _container = container;
7: }
8:
9: public Boo GetBooForFoo(int id) {
10: var boo = _container.Resolve<IMyService>().GetBooById(id);
11: return boo;
12: }
13: }
A friend of mine (Web Developer) uses the same approach (not with an IoC but an array) in PHP: He injects an array that contains every dependency. When i asked him why he is doing this that way, he told me that he doesn’t want his API to change when he needs more dependencies.
So why is this a bad decision:
- Fail Fast Principle: If the requested service IMyService in line 10 is not found, it will raise an Exception (for example an ComponentNotFoundException). In this scenario that’s no fracture of the leg but what if you would have executed some important changes before? You shouldn’t be able call a method without having the a valid starting point. It’s much better and cleaner to get an exception when you instantiating the object Foo.
- Keep in mind why you are using an container: You want to implement the Inversion of Control principle. It’s not your call that should be in control, it’s your container. It’s paradox to use an IoC-Container when you develop your code to annul the basic principle behind. Another point is that you have a hard coded dependency to a specific container implementation so you’re not able to switch you IoC-Container.
- And my last consideration is about the benefit that you’re api won’t change: Don’t hide dependencies! If you’re not the only developer that works with that code, you will get big problems because you change the components behaviour without getting errors. A developer that uses this component is wondering why his program is not working correctly any longer. Or – and that would be really upsetting – the calling component works in some cases and in some cases not for example if line 10 would be in a switch statement.
Too make a long story short: Here’s my approach
1: public class Foo : IFoo
2: {
3: private IMyService _myService;
4:
5: public Foo(IMyService myService) {
6: //you might want to do a null check
7: //what's not necessary if you unit tested your IoC right
8: _myService = myService
9: }
10:
11: //you should know what to do now
12: }