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 that are used to provide separation between the Data Access Layer and the Views.
I them needed to register this libraries AutoMapper configuration into the dependency chain.
The child library implemented its own dependency registration via an IServiceCollection extension class like so;
public static void AddDependenciesMyLibrary(this IServiceCollection services) { // register automapper services.AddAutoMapper(Assembly.GetAssembly(typeof(MyAutoMapperLibraryProfie))); // add registration of DI libraries ... }
Where we register the assembly that contains an AutoMapper : Profile extended class, as documented (sparsely) here;
In the asp .net core website that consumed this library it would also implement its own IServiceCollection extension calling;
services.AddDependenciesMyLibrary(); services.AddAutoMapper(Assembly.GetAssembly(typeof(WebAppAutoMapperProfile)));
The Issue
This would not work as the code would keep crashing with issues with the automapper not having the mapped profiles.
The reason why?
After much trial and error and reading all of the internet like this one:
Please add support for calling AddAutoMapper() multiple times…
it appears that there is a rule you must know
you can only call AddAutoMapper() once in services collection
and the first call is the one that will be retained, all subsequent calls are ignored.
The Solution
So I resolved this by adjusting the IServiceCollection Extension class as follows:
public static void AddDependenciesMyLibrary(this IServiceCollection services, IListassemblies) { // add automapper assemblies.Add(Assembly.GetAssembly(typeof(MyAutoMapperLibraryProfie))); // add registration of DI libraries ... }
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().
The client application that consumes these libraries would do the following;
// new up the assembly list var assemblies = new List(); // register DI and add to the assemblies collection services.AddDependenciesMyLibrary(assemblies); // add the apps local automapper config assemblies.Add(Assembly.GetAssembly(typeof(Startup))); // Initialise AutoMapper services.AddAutoMapper(assemblies);
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.
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.
Hope this registration pattern helps