Mapper已初始化

时间:2018-03-02 13:19:01

标签: c# .net asp.net-mvc asp.net-web-api automapper

我有一个3层架构的Web Api解决方案,里面有3个项目:数据,业务和表示层。我需要在两个业务层和表示层中初始化两个不同的映射器。

我已经创建了一个静态类和方法来初始化业务逻辑中的一个映射器:

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>());
        }
    }
}

并在此处称呼:

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();
        }


    }
}

在表示层我也做同样的事情:

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>());
        }
    }
}

并在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();
        }

我已经初始化了Mapper错误。您必须为每个应用程序域/进程调用一次Initialize。

如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

您可以使用反射和自动播放器配置文件的一种方法。这在我使用它的项目中非常有效。

在每个项目/图层中创建一个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);
        }
      });
    }

这将允许您按照所使用的图层逻辑分隔地图,并确保仅初始化它们一次。