2016-02-13 73 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>(); 
     ... 
    }); 
    ...