{"id":1662,"date":"2020-04-15T22:51:02","date_gmt":"2020-04-15T12:51:02","guid":{"rendered":"https:\/\/ntsblog.homedev.com.au\/?p=1662"},"modified":"2023-10-26T21:13:25","modified_gmt":"2023-10-26T10:13:25","slug":"net-core-automapper-dependency-injection-from-child-libraries","status":"publish","type":"post","link":"https:\/\/ntsblog.homedev.com.au\/index.php\/2020\/04\/15\/net-core-automapper-dependency-injection-from-child-libraries\/","title":{"rendered":".net Core Automapper Dependency Injection from child libraries"},"content":{"rendered":"<div id=\"ntsbl-919156401\" class=\"ntsbl-before-content ntsbl-entity-placement\"><script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js?client=ca-pub-6288941070289539\" crossorigin=\"anonymous\"><\/script><ins class=\"adsbygoogle\" style=\"display:inline-block;width:728px;height:90px;\" \ndata-ad-client=\"ca-pub-6288941070289539\" \ndata-ad-slot=\"9356781486\"><\/ins> \n<script> \n(adsbygoogle = window.adsbygoogle || []).push({}); \n<\/script>\n<\/div><h2>The Problem<\/h2>\n<p>I have recently built a set of .net core libraries that leverage automapper to help transform between my database entities and my contracts\/models that are used to provide separation between the Data Access Layer and the Views.<\/p>\n<p>I them needed to register this libraries AutoMapper configuration into the dependency chain.<\/p>\n<p>The child library implemented its own dependency registration via an IServiceCollection extension class like so;<\/p>\n<pre>public static void AddDependenciesMyLibrary(this IServiceCollection services) \n{\n\t\/\/ register automapper\n    services.AddAutoMapper(Assembly.GetAssembly(typeof(MyAutoMapperLibraryProfie)));\n\t\n    \/\/ add registration of DI libraries\n    ...\n}\n<\/pre>\n<p>Where we register the assembly that contains an AutoMapper : Profile extended class, as documented (sparsely) here;<\/p>\n<p><a href=\"https:\/\/docs.automapper.org\/en\/stable\/Dependency-injection.html#examples\"> ASPNET.Core DI Regsistration<\/a><\/p>\n<p>In the asp .net core website that consumed this library it would also implement its own IServiceCollection extension calling;<\/p>\n<pre>    \n    services.AddDependenciesMyLibrary();\n    services.AddAutoMapper(Assembly.GetAssembly(typeof(WebAppAutoMapperProfile)));\n    \n<\/pre>\n<h2>The Issue<\/h2>\n<p>This would not work as the code would keep crashing with issues with the automapper not having the mapped profiles.<\/p>\n<h2>The reason why?<\/h2>\n<p>After much trial and error and reading all of the internet like this one:<br \/>\n<a href=\"https:\/\/github.com\/AutoMapper\/AutoMapper.Extensions.Microsoft.DependencyInjection\/issues\/25\">Please add support for calling AddAutoMapper() multiple times<\/a>&#8230;<br \/>\nit appears that there is a rule you must know<\/p>\n<p><strong><em>you can only call AddAutoMapper() once in services collection<\/em><\/strong><\/p>\n<p>and the first call is the one that will be retained, all subsequent calls are ignored.<\/p>\n<h2>The Solution<\/h2>\n<p>So I resolved this by adjusting the IServiceCollection Extension class as follows:<\/p>\n<pre>public static void AddDependenciesMyLibrary(this IServiceCollection services, IList<assembly> assemblies) \n{\n\t\/\/ add automapper\n    assemblies.Add(Assembly.GetAssembly(typeof(MyAutoMapperLibraryProfie)));\n\t\n    \/\/ add registration of DI libraries\n    ...\n}\n<\/assembly><\/pre>\n<p>What this now does is traverse the Dependency chain down through my class library hierarchy and each library can maintain its own set of know assemblies, building up the collection of assemblies, but NOT calling AddAutoMapper().<\/p>\n<p>The client application that consumes these libraries would do the following;<\/p>\n<pre>\t\/\/ new up the assembly list\n\tvar assemblies = new List<assembly>(); \n\t\/\/ register DI and add to the assemblies collection\n\tservices.AddDependenciesMyLibrary(assemblies); \n\t\/\/ add the apps local automapper config \n\tassemblies.Add(Assembly.GetAssembly(typeof(Startup)));\n\t\/\/ Initialise AutoMapper\n\tservices.AddAutoMapper(assemblies);\n<\/assembly><\/pre>\n<p>This means that by the time the code returns from the Services.AddDependciesXXX call the assemblies collection will be populated with the full list of assemblies that contain AutoMapper Profiles, it is then added to locally and registered into the DI framework.<\/p>\n<p>This works and the client consuming the class library need not know anything about the internal workings of library to be able to register automapper.<\/p>\n<p>Hope this registration pattern helps<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Problem I have recently built a set of .net core libraries that leverage automapper to help transform between my database entities and my contracts\/models [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[37,5],"tags":[],"class_list":["post-1662","post","type-post","status-publish","format-standard","hentry","category-net-core","category-c"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/posts\/1662","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/comments?post=1662"}],"version-history":[{"count":0,"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/posts\/1662\/revisions"}],"wp:attachment":[{"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/media?parent=1662"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/categories?post=1662"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ntsblog.homedev.com.au\/index.php\/wp-json\/wp\/v2\/tags?post=1662"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}