{"id":8446,"date":"2017-09-07T16:15:53","date_gmt":"2017-09-07T23:15:53","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vbteam\/?p=8446"},"modified":"2024-07-05T12:36:17","modified_gmt":"2024-07-05T19:36:17","slug":"dependency-injection-with-visual-basic-net-part-2-ioc-containers","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/vbteam\/dependency-injection-with-visual-basic-net-part-2-ioc-containers\/","title":{"rendered":"Dependency Injection with Visual Basic .NET \u2013 Part 2 \u2013 IoC Containers"},"content":{"rendered":"<p><i>This post was authored by guest blogger Andr\u00e9 Obelink, a Visual Basic MVP, and published by the VBTeam on his behalf.<\/i>\nIn my previous post, I wrote about the basics of dependency injection. I explained the technique to define an interface and injecting the dependencies to a client object. These dependencies contain the real implementation of that specific interface. Applying dependency injection makes your code more loosely coupled, which helps you in maintaining, extending, and testing your codebase. The example we ended up with works fine, but it can still be improved for some scenarios. In this post I will show the use of an IoC container, a technique what can help you to make your code much flexible. It uses dependency injection to inject the correct types, based on the defined interfaces.<\/p>\n<h2>Back to the basics<\/h2>\n<p>As said, using an IoC container can help to improve your code. But to explain what we actually can improve, we should take a closer look at the code from the previous post. Starting with the context of the code example: When you were a child, and you were thirsty, you asked your mother for something to drink. You were happy when she handed you \u2018something\u2019. But what was that \u2018something\u2019 a cup of milk, a glass of orange juice, or something different? Your mother was in charge: you asked for a drink, but you didn\u2019t know in advance, what you eventually get. The following code is an excerpt from the full example in Visual Basic .NET source code:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/97d11eec9de7297106135773565c89b1.js\">\n<\/script><\/p>\n<p>In this example, the actual decision of what kind of <em>IDrinkService<\/em> is returned by the <em>GetDrinkService()<\/em> method on the <em>Mother<\/em> class is hard-coded. This isn\u2019t ideal. If you want to change the behavior of the <em>injector<\/em>, you must change the code in that class. In more complex scenarios, this can be quite hard because you must figure out where the code lives, and it can be very time consuming, especially if you must change more implementations. It isn\u2019t a best practice to have these \u2018decision code snippets\u2019 all around your code. It\u2019s much more convenient to have this composition code centrally located in one method of your application. In addition to that, you must recompile and deploy your application again. In some cases, it is obvious and not a big issue. But you can think of other examples where it would be handy to do it by simply changing one or more settings in an external configuration file. For all these scenarios, you can consider using an <em>IoC container<\/em>.<\/p>\n<h2>Inversion of control (IoC)<\/h2>\n<p>IoC stands for \u2018inversion of control\u2019. An IoC container manages the flow and logic of an application, basically in one method in your code. Mostly it is initialized during startup of your application and, depending on the defined scope, it is responsible for returning all the actual implementations for the configured interfaces. This is quite a different approach from what we are used to as more procedural programmers. You can see it as a generic framework for serving types, based on configuration. The definition of IoC on Wikipedia states more or less the same: <em>\u201cIn software engineering, inversion of control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.<\/em>\u201d\nThere are several IoC frameworks in the market today, most of them in the open-source space. If you search on the internet, you can see there are many of them. I easily found around 40! The most well-known IoC frameworks for .NET are Unity, Ninject, SimpleInjector, and Autofac. But which one should you choose? That depends\u2026 Is the framework still under active development? Most of them have their repositories on GitHub, so it\u2019s easy to verify when the last code was checked in and when the latest version was released. Another rationale could be performance of the various frameworks. It turns out that some are substantially faster than others. Or, and I think this applies in many scenarios, how good is the integration with other components? For example, with the Model-View-ViewModel (MVVM) framework you want to use in your application?\nIn this post, I\u2019ll use Autofac. But remember that fundamentally all frameworks use the same concept. They differ only in syntax and the options to configure them.<\/p>\n<h2>Concept of an IoC container<\/h2>\n<p>As said, most IoC frameworks are based on the same concept. But what is that concept? During initialization of your application, you register the types to use for the various interfaces. You \u2018tell\u2019 to the IoC container what type it should return. If the application \u2018asks\u2019 for an <em>IDrinkService<\/em>, it must deliver for example the <em>MilkDrinkService<\/em>. And this is, in short, what an IoC container does. And of course, there are several configurations possible, like for example the scope of the object. Should it be instantiated as new object every time it\u2019s needed? Or is the singleton pattern more suitable? Or is configuration hardcoded only or can you do it also with help of an external configuration file? But at the end, the main concept is the same.\nLet\u2019s see how this works out in code. In my daily life, the different implementations of an interface are mostly implemented as separate assemblies. We will take the same example as in the previous post, but we split them up in more projects.<\/p>\n<ul>\n<li>Create a new <strong>Console App<\/strong> and name it<em> DependencyInjectionVBPart02<\/em>. Rename <em>vb<\/em> to <em>MainModule.vb<\/em>. Go to the <strong>Properties Window<\/strong> of this project and set the <em>Startup object<\/em> to <em>Sub Main<\/em>.<\/li>\n<li>Add a new <strong>Class Library<\/strong> project and name it <em>Interfaces<\/em>. Delete <em>Class1.vb<\/em> and add an Interface with the name <em>IDrinkService<\/em>.<em>vb<\/em>.<\/li>\n<li>Add a new <strong>Class Library<\/strong> project and name it <em>Milk<\/em>. Rename <em>Class1.vb<\/em> to <em>DrinkService.vb<\/em>.<\/li>\n<li>Add a new <strong>Class Library<\/strong> project and name it <em>OrangeJuice<\/em>. Rename, just as in the previous step, <em>Class1.vb<\/em> to <em>DrinkService.vb<\/em>.<\/li>\n<\/ul>\n<p>All our projects are created. Now we must set the references between them. We\u2019ve created a separate project that contains the interface, in our case the <em>IDrinkService<\/em>. The reason why this is extracted to a separate assembly is that all the other projects must have knowledge of this generic part of our software. The <em>Console App<\/em>, because that code will consume the interface, and the other two libraries, because they will implement that interface. For now, we will also set references from the <em>Console App<\/em> to the two actual implementation projects. In the end of this post, you can remove those references to see a very flexible scenario. But for now:<\/p>\n<ul>\n<li>Add in <em>DependencyInjectionVBPart02<\/em>, <em>Milk <\/em>and <em>DependencyInjectionVBPart02.OrangeJuice<\/em> a project reference to <em>DependencyInjectionVBPart02.Interfaces.<\/em><\/li>\n<li>Add in <em>DependencyInjectionVBPart02<\/em> a project reference to <em>Milk<\/em> and <em>DependencyInjectionVBPart02.OrangeJuice.<\/em><\/li>\n<\/ul>\n<p>After we have set these references, we will define the <em>IDrinkService<\/em> and implement them in the other two class libraries. Change the code of <em>IDrinkService.vb<\/em> in <em>DependencyInjectionVBPart02.Interfaces<\/em> to:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/d57fa019cb6fbc5807df693e2f6bb44f.js\"><\/script><\/p>\n<p>In <em>DependencyInjectionVBPart02.Milk,<\/em> you implement the specific business logic to drink milk.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/6123d27dea5787cf1ae452d39608c6c3.js\"><\/script><\/p>\n<p>And do the same for the orange juice implementation in <em>DependencyInjectionVBPart02.OrangeJuice<\/em>.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/c1bd2045fcb5ebbd9b36797b473c40e8.js\"><\/script><\/p>\n<p>Now it\u2019s time to create the object that will consume the interface, in terms of the previous post: the <em>client object<\/em>. Add a new class to the Console App and name it <em>Child.vb<\/em>. Add the following code:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/29c3aa7cbb03d7ed73cca40c97d2028f.js\"><\/script><\/p>\n<p>Let us reflect a bit on what we have created until now. We have a class named <em>Child<\/em>, that makes use of the <em>IDrinkService<\/em> interface. Depending on the specific scenario, it gets from the <em>injector<\/em>, which in our example is an Autofac IoC container, an instance of the <em>Milk.DrinkService<\/em> or <em>OrangeJuice.DrinkService<\/em>. As said in the first post, the client object isn\u2019t aware of the actual implementations. When a new <em>Child<\/em> is instantiated, it gets one of the two <em>DrinkServices<\/em> injected.\nFinally, we are at the point where the IoC container comes in place. As shown at the beginning of the post, the <em>Mother<\/em> was used as injector and it was responsible for creating the instance of, for example, the <em>MilkDrinkService<\/em>. Creation of new specific objects from code is what you want to prevent when using an IoC container. So, this is where the code in this post will be really going different.\nAdd to our <em>Console App<\/em> the <strong>Autofac<\/strong> NuGet Package.<\/p>\n<blockquote><p>PM&gt; Install-Package Autofac -Version 4.6.0<\/p><\/blockquote>\n<p>To use an IoC container, we must define the container and build or construct it using a <em>ContainerBuilder<\/em>. Add the following code to <em>MainModule.vb<\/em>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/0729b086e11677ab4deac5b77d2c40a5.js\"><\/script><\/p>\n<p>The <em>InitializeContainer()<\/em> method is responsible for registering or mapping of the implementation types to the corresponding interfaces. As you can see, we are \u2018telling\u2019 the container that when we are \u2018asking\u2019 for an object of the type <em>IDrinkService<\/em> that an object of the type <em>Milk.DrinkService<\/em> must be returned. You can imagine that you can register more than one type in this method, and we will do this later.\nI think you want to see this code in action, but we aren\u2019t finished yet. What is missing is the code to call all this magic. Add the following code to <em>Sub Main()<\/em>:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/f416257fa2902cef40d7e52e0089d306.js\"><\/script><\/p>\n<p>Hit F5 and\u2026 voila!<\/p>\n<p>We can go one step further and demonstrate a feature of Autofac to support constructor injection automatically. Let\u2019s introduce a new interface <em>IChild<\/em>. Add a new interface to our class library with interfaces, <em>DependencyInjectionVBPart02.Interfaces<\/em>. Name it <em>IChild.vb<\/em> and add the following code:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/54ea8cdae6de08bf6742a5f5810b3092.js\"><\/script><\/p>\n<p>Modify the current <em>Child.vb<\/em> class to implement the interface just created:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/d82ed96e46160ea6ec108f4b5484450c.js\"><\/script><\/p>\n<p>Remember, introducing a new interface means that we must register this type in our <em>InitializeContainer()<\/em> method. Modify this method and add a new line under the existing one where we register the <em>Milk.DrinkService<\/em>.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/08f45a08876b28cd2166436aef214f29.js\"><\/script><\/p>\n<p>Now, after we\u2019ve registered the <em>IChild<\/em> interface, we can ask the IoC container to resolve the <em>Child<\/em> object. Run our application and note that this is also working as expected.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/f73f59a2304519ee367e2957ae75825b.js\"><\/script><\/p>\n<p>Let\u2019s summarize what\u2019s happening here:<\/p>\n<ul>\n<li>The <em>Main()<\/em> method asks the container for an <em>IChild<\/em>;<\/li>\n<li>The container sees that <em>IChild<\/em> maps to <em>Child,<\/em> so it starts creating a <em>Child<\/em>;<\/li>\n<li>The container sees that the <em>Child<\/em> needs an <em>IDrinkService<\/em> in its constructor;<\/li>\n<li>The container sees that <em>IDrinkService<\/em> maps to <em>DrinkService<\/em>, so it creates a new <em>Milk.DrinkService<\/em> instance;<\/li>\n<li>The container uses the new <em>DrinkService<\/em> instance to finish constructing <em>Child<\/em>;<\/li>\n<li>The container returns the fully constructed <em>Child<\/em> to the <em>Main()<\/em> method to consume.<\/li>\n<\/ul>\n<p>As you can see, it\u2019s quite impressive how smart Autofac, and most of the other IoC containers, are in dealing with this kind of dependency-resolving and injection.<\/p>\n<h2>Use of a configuration file<\/h2>\n<p>What you\u2019ve seen is pretty cool, but it can still a bit cooler. The construction of our container is still hard-coded in our application. Even though this way of configuration is encouraged by Autofac, in some scenarios you need ultimate flexibility. An example could be that you want to change the behavior of your software, without recompiling your application. For these kinds of technical requirements, you can extract the configuration out of the source code and place it in an external file. To establish this, we must add two other NuGet packages to the Console App: <em>Autofac.Configuration<\/em> and <em>Microsoft.Extensions.Configuration.Json<\/em>. Use the <strong>NuGet Package Manager Window<\/strong> in Visual Studio as shown earlier or enter the following commands in the <strong>Package Manager Console<\/strong>:<\/p>\n<blockquote><p>PM&gt; Install-Package Autofac.Configuration -Version 4.0.1\nPM&gt; Install-Package Microsoft.Extensions.Configuration.Json -Version 1.1.2<\/p><\/blockquote>\n<p>When installing these two NuGet packages, many other packages are also pulled in. If you need to support XML files instead of JSON, you can install <em>Microsoft.Extensions.Configuration.Xml<\/em> instead of the JSON-variant. The basic steps to getting configuration set up with an external file and your application are:<\/p>\n<ul>\n<li>Set up your configuration in JSON files that can be read by <em>Extensions.Configuration<\/em>. JSON configuration uses <em>Microsoft.Extensions.Configuration.Json<\/em> implementation.<\/li>\n<li>Build the configuration using the <em>Extensions.Configuration.ConfigurationBuilder<\/em>.<\/li>\n<li>Create a new <em>Configuration.ConfigurationModule<\/em> and pass the built <em>Microsoft.Extensions.Configuration.IConfiguration<\/em> into it.<\/li>\n<li>Register the <em>Configuration.ConfigurationModule<\/em> with your container.<\/li>\n<\/ul>\n<p>This theory translated to Visual Basic .NET means that we have to rewrite our <em>InitializeContainer()<\/em> method.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/0d8a61267a28f30b96f934f60981918f.js\"><\/script><\/p>\n<p>If you\u2019ve read the basic steps thoroughly, you might have noticed that we skipped the first step. We still need to create the configuration file. Add to the Console App an additional item of type JSON file. Give it the name <em>Autofac.json<\/em>. Go to the properties of this file in the <strong>Solution Explorer<\/strong> and set the value of \u2018Copy to Output Directory\u2019 to the value of \u2018Copy if newer\u2019. This ensures that our executable can find the JSON file in its own directory when is executed. Copy and paste the following JSON into this file.<\/p>\n<p><script src=\"https:\/\/gist.github.com\/obelink\/c03da677c922d05cdf1967fff284e40f.js\"><\/script><\/p>\n<p>The format of this file \u2013 and all possible options &#8211; is described in detail <a href=\"http:\/\/docs.autofac.org\/en\/latest\/configuration\/xml.html\">on the web site of Autofac<\/a>.But in the end, what you can see in this file is the same as what we wrote in the code. We register the type and map it to its corresponding interface. The first parameter of the \u2018type\u2019 attribute is the name of the class, including the full namespace. After that and separated by a comma, the second parameter. This is the name of the assembly where this type or interface lives (without the extension .EXE or .DLL).\nWhen you run the application, you can see that it still works as expected!<\/p>\n<p>In theory, you can now delete the references set in the Console App to <em>DependencyInjectionVBPart02.Milk<\/em> and <em>DependencyInjectionVBPart02.OrangeJuice<\/em>. Your application doesn\u2019t have to know about these implementations. It\u2019s all done by configuration in the external JSON file. But, if you do so, be aware that if the references are missing, these class libraries won\u2019t be built automatically when you start the application. When these assemblies already exist in the output directory and nothing has changed, there is no problem. But when you changed something in a class library and you see that the old logic is still used, don\u2019t forget to choose <em>Rebuild Solution. <\/em>You won\u2019t be the first person who encounters this \u2018problem\u2019 and you will definitely not be the last!\nIn this post, I\u2019ve showed you how to use an IoC container. Using this technique can make your code much more flexible and easier to maintain. I recommend you to give it a try in your current, or one of your next projects. It&#8217;ll make your life much easier.\nHappy coding!\nAndr\u00e9 Obelink\nTwitter: <a href=\"https:\/\/twitter.com\/obelink\">@obelink<\/a>\nBlog: <a href=\"http:\/\/www.obelink.com\">www.obelink.com<\/a><\/p>\n<p>Links:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/vbteam\/dependency-injection-with-visual-basic-net-part-1\/\">Dependency injection with Visual Basic .NET \u2013 Part 1<\/a><\/li>\n<li><a href=\"https:\/\/autofac.org\">autofac.org<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/obelink\/DependencyInjectionVBPart02\">https:\/\/github.com\/obelink\/DependencyInjectionVBPart02<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This post was authored by guest blogger Andr\u00e9 Obelink, a Visual Basic MVP, and published by the VBTeam on his behalf. In my previous post, I wrote about the basics of dependency injection. I explained the technique to define an interface and injecting the dependencies to a client object. These dependencies contain the real implementation [&hellip;]<\/p>\n","protected":false},"author":260,"featured_media":8818,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[19,195],"tags":[],"class_list":["post-8446","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-community-contribution","category-visual-basic"],"acf":[],"blog_post_summary":"<p>This post was authored by guest blogger Andr\u00e9 Obelink, a Visual Basic MVP, and published by the VBTeam on his behalf. In my previous post, I wrote about the basics of dependency injection. I explained the technique to define an interface and injecting the dependencies to a client object. These dependencies contain the real implementation [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/8446","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/users\/260"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/comments?post=8446"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/posts\/8446\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media\/8818"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/media?parent=8446"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/categories?post=8446"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/vbteam\/wp-json\/wp\/v2\/tags?post=8446"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}