2016-02-13 78 views
20

我试图找出我的应用程序的Startup.cs文件来配置AutoMapper,然后用它在我的应用程序的正确方法。配置AutoMapper 4.2,内置在国际奥委会ASP.NET 1.0的核心MVC6

我想使用this documentation这在一定程度解释了如何仍给AutoMapper静态的感觉没有老静态API。该示例使用StructureMap。

我想知道我可以做同样的事情,但在使用内置的服务容器中的核心应用程序1.0。

我假设在配置功能我将配置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); 
} 

它根本无法所有工作..我必须错过一些步骤或做错事。

+0

我没有这样做的完整的答案(它挣扎喽!),但在你的AddTransient,第二通用参数是Mapper的*类型*而不是使用CreateMapper创建的Mapper实例。我猜这将是沿着services.AddInstance的行。 – DavidGouge

回答

36

这个答案适合MVC 6的方法多了几分控制器层周围:

我从AutoMapper 4.1.1迁移到4.2.0,有一个很少有问题找出错综复杂的问题,但最终到了那里。

首先我分开AutoMapper简介建设成一个新的类(见下文),以节省堵塞启动类。

using AutoMapper; 
using YourModels; 
using YourViewModels; 

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

我对启动类做了以下修改。

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

private MapperConfiguration _mapperConfiguration { get; set; } 

在启动构造函数添加以下代码来实例化我的新AutoMapper档案。

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

ConfigureServices()我放弃了我的新AutoMapper档案到一个单。

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

然后,它只是一个简单的操作注入相关的控制器。

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

     ... 
} 

感谢Rexebin在https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/的帮助,感谢他的博文。

4

在你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; 
     } 
} 
0

我只是从.NET 4.5在移动网络的API .NET核试验,需要这一点。你非常接近,因为@DavidGouge建议你需要注册你在IOC中创建的映射器实例。因此,AutoMapper配置需要在ConfigureServices中完成。 (已包含在这里,但在我的项目中它调用了AutoMapperConfiguration类中的方法,所以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. 
    } 
3

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

在Startup.cs在配置方法的顶部只需编写下面的代码来初始化的映射:

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

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

Mapper.Map<Product>(productViewModel); 
7

您也可以使用automapper创建者的扩展包。

您可以传入配置,指定程序集扫描或不传递任何东西,并让它从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>(); 
     ... 
    }); 
    ...