Company information
Fill up the form and we will contact you shortly.
ServoCode Sp. z o.o.
Jasionka 954E, 36-002 Jasionka, Poland
NIP: 8133719852
REGON: 364182909
KRS: 0000611643
Today I would like to make you familiar (especially Junior Developers) with an elementary yet powerful concept – Dependency Injection.
First things first. Dependency Injection is a technique or methodology where object dependencies are externally supplied to given object. This is the direct realization of IoC (Inversion of Control). I suppose it doesn't explain you much. I know it sounds like magic, but I will explain both concepts with examples. :)
Let's consider the following code:
Implementation details are not relevant here. The most important thing is that we created abstraction (IUserRepository interface) and implementation (UserRepository class). Creating this instance is pretty straightforward and can be done via this code:
Now let's create another layer which would use repositories:
Brilliant! Now we have a service which uses our repository. The big question is: what is wrong with that piece of code? We created an instance of a concrete class in service constructor. Well, it's nothing wrong with using constructors in code, but lets consider 3 following cases:
1. One developer decided to implement their own version of UserRepository. Turns out that this implementation is way better than currently used one. Such a shame our project has about 60 services which use UserRepository… Now we have to change it everywhere, which is pretty simple. Harder part is to make the change and not to make a mistake.
2. Another brilliant developer created a non-default constructor in UserRepository. We get to the same point as in the first scenario.
3. Outstanding developer had an idea to write services unit tests. Not going to happen! Why? They can’t! Services strongly rely on concrete repository implementation which in fact can access the database or do plenty of different stuff.
After all these horror stories, I'm introducing you to the resolver:
Again, implementation is not relevant here. There are 2 main functions:
1. Register binds together an interface and its implementation.
2. Resolve retrieves a specific object of given class/interface.
Somewhere in the main application class in assembly far far away we register our repository like that:
Now let's improve the service code a bit:
From this moment, feel free to not care about repository implementation, we just ask our resolver for the object associated with the interface. Our outstanding developer would be satisfied as he can now create interface mock and write unit tests. But still, it is not fully implemented IoC and Dependency Injection. There is just one thing we have to change:
After adding this tiny line of code, we do not even need to know how resolving works. Everything we want is injected via constructor into our service, and therefore we can use it without any limitations.
The trickier part is how to create a fully inverted application which for examples performs navigation between different views, binds models to them with all dependencies, etc. But that is really technology dependent topic and (perhaps) the topic of our other considerations. :)
How to rescue a bad code in C#
Have an idea ? Let’s talk
Fill up the form and we will contact you shortly.
ServoCode Sp. z o.o.
Jasionka 954E, 36-002 Jasionka, Poland
NIP: 8133719852
REGON: 364182909
KRS: 0000611643
Your message has been sent!
Your message has been sent!