在 ASP.NET Core 1.0 MVC6 中使用内置 IoC 配置 AutoMapper 4.2

Configuring AutoMapper 4.2 with built in IoC in ASP.NET Core 1.0 MVC6

我正在尝试找出在我的应用程序的 Startup.cs 文件中配置 AutoMapper 的正确方法,然后在我的整个应用程序中使用它。

我正在尝试使用 this documentation,这在某种程度上解释了如何在没有旧静态 API 的情况下仍然为 AutoMapper 提供静态感觉。该示例使用 StructureMap。

我想知道如何在使用内置服务容器的 Core 1.0 应用程序中做类似的事情。

我假设我将在 Configure 函数中配置 AutoMapper,然后在 ConfigureServices 函数中将其添加为瞬态。

我最终假设最干净和最正确的方法是使用依赖注入。这是我目前的尝试,但没有用:

Startup.cs

public IMapper Mapper { get; set; }
private MapperConfiguration MapperConfiguration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
     services.AddTransient<IMapper, Mapper>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    MapperConfiguration MapperConfiguration = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Product, ProductViewModel>().ReverseMap();
    });

    Mapper = MapperConfiguration.CreateMapper();
}

在我的控制器中:

private IMapper _mapper { get; set; }
// Constructor
public ProductsController(IMapper mapper)
{
    _mapper = mapper;
}

public IActionResult Create(ProductViewModel vm)
{
    Product product = _mapper.Map<ProductViewModel, Product>(vm);
}

它根本不起作用...我一定是遗漏了某些步骤或做错了什么。

在您的 ConfigurationServices 中,您可以新建一个 MapperConfiguration 实例,然后创建您的地图并添加它们。

public void ConfigureServices(IServiceCollection services)
{     
    MapperConfiguration configuration = new MapperConfiguration(cfg =>
    {
       cfg.AddProfile<MappingProfile.Profile1>();
       cfg.AddProfile<MappingProfile.Profile2>();
    });

    services.AddInstance(typeof (IMapper), configuration.CreateMapper());
}

然后你只需在构造函数和映射中注入 IMapper

public class Handler
{
      private readonly ProfileContext _db;
      private readonly IMapper _mapper;

      public Handler(ProfileContext db, IMapper mapper)
      {
          _db = db;
          _mapper = mapper;
      }

      public void Handle(Profile1 request)
      {

          ProfileModel profile = _mapper.Map<Profile1, ProfileModel>(request);

          _db.Profiles.Add(profile);

          try
          {
              db.SaveChanges();
          }
          catch (Exception ex)
          {

              throw;
          }

          return profile;
      }
}

我正在尝试将 Web API 从 .net 4.5 迁移到 .net core,并且需要这个。你非常接近,因为@DavidGouge 建议你需要注册你在 IOC 中创建的映射器实例。所以AutoMapper的配置需要在ConfigureServices中进行。 (这里已经包含在行中,但在我的项目中它调用了 AutoMapperConfiguration class 中的方法,因此 Startup 尽可能保持干净,与 IOC 注册相同)。然后 IMapper 将正确填充到您的控制器中。

Startup.cs 变为

   public IMapper Mapper { get; set; }
   private MapperConfiguration MapperConfiguration { get; set; }
   public void ConfigureServices(IServiceCollection services)
   {
        MapperConfiguration MapperConfiguration = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Product, ProductViewModel>().ReverseMap();
        });

        Mapper = MapperConfiguration.CreateMapper();

        services.AddInstance(Mapper);
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // AutoMapper Configuration moved out of here.
    }

这个答案更适合控制器层周围的 MVC 6 方法:

我从 AutoMapper 4.1.1 迁移到 4.2.0,在解决错综复杂的问题时遇到了一些问题,但最终还是成功了。

首先,我将 AutoMapper 配置文件构建到一个新的 class(见下文)中,以避免堵塞启动 class。

using AutoMapper;
using YourModels;
using YourViewModels;

namespace YourNamespace
{
    public class AutoMapperProfileConfiguration : Profile
    {
        protected override void Configure()
        {
            CreateMap<Application, ApplicationViewModel>();
            CreateMap<ApplicationViewModel, Application>();
            ...
        }
    }
}

我对 Startup 进行了以下修改 class。

我添加了 MapperConfiguration 类型的私有成员变量。

private MapperConfiguration _mapperConfiguration { get; set; }

在启动构造函数中,我添加了以下代码来实例化我的新 AutoMapper 配置文件。

_mapperConfiguration = new MapperConfiguration(cfg =>
{
    cfg.AddProfile(new AutoMapperProfileConfiguration());
});

ConfigureServices() 中,我将新的 AutoMapper Profile 放到了单例中。

services.AddSingleton<IMapper>(sp => _mapperConfiguration.CreateMapper());

然后就是一个简单的操作,给它注入相关的controller。

using AutoMapper;
using ...

namespace YourNamespace
{
    public class ApplicationsController : BaseController
    {
        [FromServices]
        private IMapper _mapper { get; set; }

        [FromServices]
        private IApplicationRepository _applicationRepository { get; set; }

        public ApplicationsController(
            IMapper mapper,
            IApplicationRepository applicationRepository)
        {
            _mapper = mapper;
            _applicationRepository = applicationRepository;
        }

        // GET: Applications
        public async Task<IActionResult> Index()
        {
            IEnumerable<Application> applications = await _applicationRepository.GetForIdAsync(...);

            if (applications == null)
                return HttpNotFound();

            List<ApplicationViewModel> viewModel = _mapper.Map<List<ApplicationViewModel>>(applications);

            return View(viewModel);
        }

        ...
}

感谢 https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/ 的 Rexebin post 提供了极大的帮助。

发布的答案是一个很好的解决方案,但我想我会让你们知道我目前是如何使用 Core 1.0 和 AutoMapper v5.1.1 来解决这个问题的。我觉得这是一个很好的方法,也很容易理解。

在 Configure 方法顶部的 Startup.cs 中,只需编写以下代码来初始化您的映射:

Mapper.Initialize(config =>
{
     config.CreateMap<ProductViewModel, Product>().ReverseMap();
     config.CreateMap<CustomerViewModel, Customer>().ReverseMap();
});

然后在您的控制器或您需要映射的代码的任何其他部分:

Mapper.Map<Product>(productViewModel);

您也可以使用来自自动映射器创建者的扩展包。

您可以传入一个配置,指定要扫描的程序集,或者不传递任何内容,让它从 DependencyContext 扫描程序集。

https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection

https://www.nuget.org/packages/AutoMapper.Extensions.Microsoft.DependencyInjection/

public void ConfigureServices(IServiceCollection services)
{
    //configure DI
    services.AddTransient<IFoo, Foo>();

    //Add automapper - scans for Profiles
    services.AddAutoMapper();
    //or specify
    services.AddAutoMapper(cfg =>
    {
        cfg.AddProfile<ViewModelProfile>();
        ...
    });
    ...