Mapper is already initialized

I have a three-layer Web Api architecture with three projects inside: data, business and presentation layers. I need to initialize two different cartographers in two business and presentation layers.

I created a static class and method to initialize a single handler in business logic:

using AutoMapper;
using Shop.BLL.DTOModels;
using Shop.DAL.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shop.BLL.InitMapper
{
    public static class InitializeMapperBLL
    {
        public static void RegisterMappings()
        {
            Mapper.Initialize(cfg => cfg.CreateMap<Category, DTOCategoryModel>());
        }
    }
}

And call it like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Shop.DAL.Repositories;
using AutoMapper;
using Shop.BLL.DTOModels;
using Shop.DAL.Models;
using Shop.BLL.Interfaces;
using Shop.DAL.Interfaces;
using Shop.BLL.InitMapper;

namespace Shop.BLL.Services
{
    public class CategoryService : ICategoryService
    {
        IUnitOfWork Database { get; set; }

        public CategoryService(IUnitOfWork uow)
        {
            Database = uow;
        }

        public IEnumerable<DTOCategoryModel> GetCategories()
        {
//I call it here
            InitializeMapperBLL.RegisterMappings();

            return Mapper.Map<IEnumerable<Category>, List<DTOCategoryModel>>(Database.Categories.GetAll());
        }
        public void Dispose()
        {
            Database.Dispose();
        }


    }
}

And in the presentation layer, I do the same:

using AutoMapper;
using Shop.API.ViewModels;
using Shop.BLL.DTOModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Shop.API.MapperInit
{
    public static class InitializeMapperAPI
    {
        public static void RegisterMappings()
        {
            Mapper.Initialize(cfg => cfg.CreateMap<DTOCategoryModel, CategoryViewModel>());
        }
    }
}

And call Global.asax

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
      //here I call it
            InitializeMapperAPI.RegisterMappings();

            CreateKernel();
        }

And I already have a Mapper error. You must call Initialize once per application domain / process.

How to solve this problem?

+4
source share
1 answer

One way to do this is to use reflection profiles and autocouples. This worked very well in projects in which I used them.

automapper /. , . , , :

  //Profile here is of type AutoMapper.Profile
  public class BusinessLayerMapperConfig : Profile
  {
    public BusinessLayerMapperConfig()
    {
      //create layer specific maps
      CreateMap<MyObjectDTO, MyObjectViewModel>();
    }

    public override string ProfileName
    {
      get { return this.GetType().ToString(); }
    }
  }

- ( ApplicationStart Global.asax.cs), :

public static void RegisterMaps()
    {
      //get all projects' AutoMapper profiles using reflection
      var assembliesToScan = System.AppDomain.CurrentDomain.GetAssemblies();
      var allTypes = assembliesToScan.SelectMany(a => a.ExportedTypes).ToArray();

      var profiles =
          allTypes
              .Where(t => typeof(Profile).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo()))
              .Where(t => !t.GetTypeInfo().IsAbstract);

      //add each profile to our static AutoMapper
      Mapper.Initialize(cfg =>
      {
        foreach (var profile in profiles)
        {
          cfg.AddProfile(profile);
        }
      });
    }

, , .

0

Source: https://habr.com/ru/post/1694354/


All Articles