Configuring Automapper in N-Layer application

2020-07-17 08:23发布

问题:

I have an N-Layer application as shown below

MyApp.Model - contains edmx and data models

MyApp.DataAccess - Repositories with EF

MyApp.Domain - Domain/business models

MyApp.Services - services(class library)

MyApp.Api - ASP.NET Web API

I am using Unity as my IoC container and Automapper for OO mapping.

My DataAccess layer references Model layer which contains all my Data objects.

I do not want to refer my model project in my Api layer. So returning DomainObjects (business models) from service layer and mapping to DTOs in API layer(DTOs are in API layer).

I configured domainModel to DTO mapping in API layer as below

public static class MapperConfig
{
    public static void Configure() {
        Mapper.Initialize(
            config => {
                config.CreateMap<StateModel, StateDto>();
                config.CreateMap<StateDto, StateModel>();

                //can't do this as I do not have reference for State which is in MyApp.Model
                //config.CreateMap<State, StateModel>();
                //config.CreateMap<StateModel, State>();
            });
    }
}

Now my question is how/where to configure my auto mapper mappings to convert my Entity models to Domain models?

To do in my API layer I do not have reference to my model project. I believe I should do this in service layer but not sure how to do that. Please help how to configure this mapping.

Note: Before asking here I googled with all eyes

  1. Where to place AutoMapper map registration in referenced dll says to use static constructor which I do not think a good option to add in all my models (I have 100 models) and another answer says to use PreApplicationStartMethod for which I have to add reference to System.web.dll to my services which is not correct.

  2. https://groups.google.com/forum/#!topic/automapper-users/TNgj9VHGjwg also did not answer my question properly.

回答1:

You need to create mapping profiles in each of your layer projects, then tell AutoMapper to use those profiles in the topmost/outermost (invoking) layer that references all the lower layers. In your example:

MyApp.Model

public class ModelMappingProfile : AutoMapper.Profile
{
    public ModelMappingProfile()
    {
        CreateMap<StateModel, StateDto>();
        CreateMap<StateDto, StateModel>();
    }
}

MyApp.Api

public class ApiMappingProfile : AutoMapper.Profile
{
    public ApiMappingProfile()
    {
        CreateMap<State, StateModel>();
        CreateMap<StateModel, State>();
    }
}

MyApp.Services

Mapper.Initialize(cfg => 
{
    cfg.AddProfile<MyApp.Model.ModelMappingProfile>();
    cfg.AddProfile<MyApp.Model.ApiMappingProfile>();
});

or if you are using a DI container (e.g. SimpleInjector):

container.RegisterSingleton<IMapper>(() => new Mapper(new MapperConfiguration(cfg => 
{
    cfg.AddProfile<MyApp.Model.ModelMappingProfile>();
    cfg.AddProfile<MyApp.Model.ApiMappingProfile>();
})));