我正在尝试找出在我的应用程序的Startup.cs文件中配置AutoMapper的正确方法,然后在整个应用程序中使用它。
我正在尝试使用this documentation,它解释了如何在没有旧的静态API的情况下仍然给予AutoMapper静态的感觉。该示例使用StructureMap。
我想知道我可以做些类似的事情,但是在使用内置服务容器的Core 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 :(得分:37)
这个答案更适合围绕Controller层的MVC 6方法:
我从AutoMapper 4.1.1迁移到4.2.0,有一些问题找出错综复杂但最终到达那里。
首先,我将AutoMapper Profile构建分离为一个新类(见下文),以节省启动类的阻塞。
using AutoMapper;
using YourModels;
using YourViewModels;
namespace YourNamespace
{
public class AutoMapperProfileConfiguration : Profile
{
protected override void Configure()
{
CreateMap<Application, ApplicationViewModel>();
CreateMap<ApplicationViewModel, Application>();
...
}
}
}
我对Startup类进行了以下修改。
我添加了MapperConfiguration类型的私有成员变量。
private MapperConfiguration _mapperConfiguration { get; set; }
在Startup构造函数中,我添加了以下代码来实例化我的新AutoMapper Profile。
_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/的帖子,感谢他的帮助。
答案 1 :(得分: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>();
...
});
...
答案 2 :(得分: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;
}
}
答案 3 :(得分:3)
发布的答案是一个很好的解决方案,但我想我会让你们知道我目前是如何使用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);
答案 4 :(得分:0)
我只是在尝试将Web API从.net 4.5迁移到.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.
}