Dependency Injection – professional containers

I’m after a long break πŸ™‚ prepares for a presentation about CQRS, which will be recorded in Gdansk, I will post it on the blog πŸ™‚ And all the time work on the startup is boiling πŸ™‚ But let’s get to the point πŸ™‚ as promised in the previous article, next will be about these professional containers, it’s worth to use them because the possibilities are big πŸ™‚ We’re going πŸ™‚


Admission

The question “Why not use my own container?” I answered in the previous article about containers in the introduction.

Well not quite the best … πŸ™‚

In this article I will describe a few containers of their advantages, disadvantages and basic functionalities, with such a selection of IoC containers, writing your own container is simply pointless …

And what should doing such a container? This is what I will describe on specific examples of containers πŸ™‚


Pros and cons of containers

The main advantage of containers is definitely that they facilitate the creation of class instances with prior registration, so that the container knows about their existence.

The next advantage is that they make it easier to write tests (which is very important to me), as I showed in the previous article πŸ™‚

And the main disadvantage is that the containers at the beginning are difficult to understand, unfortunately … Some people think that containers are unnecessary because they only make it difficult to understand the application. However, with time, when you get to the point, it will be easy πŸ™‚ I will try to make it easy to read this article πŸ™‚


Ninject

The first in the queue is Ninject written by Nate Kohari.

So what should a self-respecting container have?

For sure, it should be able to download all classes of a given interface to be able to display it later using IEnumerable we will do it using Ninject πŸ™‚

The first thing we should do is to delete everything that was associated with our container from the previous article and in the Main() function in the WebServer class do something like:

Inside the Ninject, so in the kernel, we create an instance of the Bindings class in which all classes registered by us are present.

Next, we download all instances of the ICharacter interface to the IEnumerable collection and display them in the foreach loop.

It is also known that in the ResolveInterfaces() method, which serves as our constructor in the GameServer class, we must get the classes that we previously registered.

And what are the changes in the tests? There is very little change. Only the TestSetup() method in the GameServerClassTest class is changed.

We pass this merits, that is how classes are registered. Let’s see the Bindings class

All classes are registered here.

The final result looks like this:

There is one problem in the Bindings class. This way of registering is not the best, what if we had … thirty classes and thirty different interfaces? A bit of sham … You would have to write all classes in turn …

But wait … will not a self-respecting container be able to register all classes in the system? I will answer this question soon because I will show on the example of the StructureMap container πŸ™‚


StructureMap

Answering the above question – Yes, it should be possible, but it will show how to do it using the container as in the title of this point πŸ™‚

We change the code in the same places as in the previous example. Let’s start with the Main() function.

We have this code:

And that’s enough to register all classes. And creating an instance of the GameServer class is other tale we just need to call the ResolveInterfaces() method, which also changes to something like this:

In the production code, luckily, you can do everything automatically. Only in the tests we have to give the classes we want to register.

And of course the result πŸ™‚

Let’s move to container called the Castle Windsor


Castle Windsor

Here I will show only how to use it. First, let’s see the changes in the Main() function

So first we register dependencies, and create GameServer instances. Here we also have to register the GameServer class itself to create its instance.

There are such changes in the ResolveInterfaces() method:

In tests, just put the same as in the Main () function without any changes πŸ™‚

We’re still creating instances of classes all the time, but can we manage their life cycle? So, for example, tell the container to create only one instance of the object, or treat the instance as a singleton.

By the way, another great advantage of containers is the ability to work efficiently with them. For example, you can see how Castle Windsor debugging works. Nice πŸ™‚ https://github.com/castleproject/Windsor/blob/master/docs/debugger-views.md

Our container from the previous article has always created a new object instance which in larger systems is unacceptable, ignoring the fact that we should always clean our container at the end of the application, because the created instances are forever in the container if we do not clean them. πŸ™‚

We will manage the life cycle of our facilities using the Unity container.

Of course, all these containers are from the .Net platform in other platforms there are other containers.



Unity

One by one, before we manage the object lifecycle, we first register the objects in the Main() function in this way:

Those objects that we gave as arguments to the registering methods determine whether the object will be a singleton or whether it will be a singleton of a registered class that will not share an instance with the so-called parent container. It may seem confusing, but soon it will become clear first let’s see how we will check whether the object is singleton or not.

In the LoginValidator class, I created a public variable and method, something like this:

The same in the CharacterSkillPoints classes, PasswordValidator.

We will call the CountNumberOfCalling() method, if the object is a singleton, we should display a number greater than 1 on the console.

Let’s start with the first TransientLifetimeManager object, type in something like this under the class registration:

Of course, to make it work, we still need to create a GameServer object:

And change the ResolveInterfaces() method.

The result is this:

So we see that if we give the TransientLifetimeManager object as an argument, it will always create a new instance of the class.

Let’s move to the next ContainerControlledLifetimeManager this object will create singletons for us. So the Main () function:

As we can see the CountNumberOfCalling() method has been called twice in the same object, si it is a singleton πŸ™‚

Let’s move to the last HierarchicalLifetimeManager object works the same as the previous one, only one difference is that you can create a container child using this object, which also creates a singleton, but it will not share the instance with own container. The example should be more understandable. πŸ™‚

We create a singleton instance and then a container child and use it to create another singleton.

The result is this:

And that’s more or less the management of object life cycles looks like, let’s go over the last container I use and use most often πŸ™‚


Autofac

Let’s see the basic use of Autofac, let’s start with the Main() function:

And changes in the ResolveInterfaces() method

The changes in the tests are the same as in the Main() function.

But this is not the end of the advantages of ready containers, another advantage is, for example, that you can register the factories giving as a dependence of Func<Interface> or a delegate. In this way, we can create a relationship when it is really needed and also do not expose the container to the components being created. Let me give you an example πŸ™‚

First, we create a class with a delegate:

Through this delegate, we will create our DelegateClass class in the Main() function.

In Main, we create a delegate instance and pass the appropriate argument. The result is this:

The next article will be entirely about Autofac, so about this point will be more detail already using Func in the next article, not only delegates πŸ™‚


Other advantages of containers

Well, are all the advantages of containers? Of course not πŸ™‚

Containers allow us to use aspect programming. Everywhere in which companies I was aspect programming was used to a greater or lesser extent. In short, aspect programming involves separating the logic of eg caching or logging from business logic. It’s so in a nutshell. Personally, I think this is a very interesting solution, it is definitely worth the interest.

Here is a bit about aspect programming: https://dzone.com/articles/aspect-oriented-programming-in-c-using-dispatchpro

Ready containers certainly work faster than ours. And they are written for years in teams of really experienced programmers.


Which container should I choose?

Well, certainly not speed, I do not care whether I will have a class instance created in a few or a dozen milliseconds …

Rather, I think to pay the most attention to the possibilities and the syntax of the container. For example, the Register and Resolve methods can be implemented in as many different ways as there are programmers on the ground, but in some containers, in my opinion, the syntax is too complicated …

And always remember to also change the code for the container you use w in tests πŸ™‚


Summary

In the next article I will describe more precisely the Autofac container, which is the one I use most often πŸ™‚

Link to github with the whole code from this article: https://github.com/Slaw145/DIContainers

This content also you can find on medium: https://medium.com/@sawomirkowalski/dependency-injection-professional-conainers-814f200f6b6d

As a standard, I remind you about the newsletter, which I send notifications about new entries and additional information about the IT world in general.

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 

– site on fb: Devman.pl-Slawomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want πŸ™‚

 
If that post was useful for you share it with your friends :)

Post a comment

avatar
  Subscribe  
Notify about