简体   繁体   English

将 Automapper 与 ASP.NET Core 结合使用

[英]Using Automapper with ASP.NET Core

I´m trying to use Automapper with Dependency Injection configuration on a n-layer application.我正在尝试在 n 层应用程序上使用具有依赖注入配置的 Automapper。

 public class ApplicationMapping : Profile
{
    public ApplicationMapping()
    {
        RegisterMappings();
        Mapper.AssertConfigurationIsValid();
    }  

    private void RegisterMappings()
    {
      CreateMap<IEnumerable<App>, ListAppsDto>()
            .ForMember(dest => dest.Apps,
                       opt => opt.MapFrom(src =>
                            Mapper.Map<IEnumerable<App>, List<App>>(src.ToList())
                           )
                      );
    }
}

This class is inside my Application dll, where I put my services and DTOs.这个类位于我的Application dll 中,我在其中放置了我的服务和 DTO。 Also in this dll, I have an extension method to register the mapping:同样在这个 dll 中,我有一个扩展方法来注册映射:

 public static class MappingServiceExtension
{
    public static void AddApplicationMappings(this IServiceCollection services)
    {
        var mapperConfig = new MapperConfiguration(config =>
        {
            config.AddProfile<ApplicationMapping>();
        });

        IMapper mapper = mapperConfig.CreateMapper();
        services.AddSingleton(mapper);
    }
}

Then in my WebAPI project, on the Startup.cs class I put:然后在我的 WebAPI 项目中,在Startup.cs类上我放了:

  services.AddApplicationMappings();

And I use it normally with DI in my services:我通常在我的服务中将它与 DI 一起使用:

  public class AppService : IAppService
 {
    private readonly IAppRepository _appRepository;
    private readonly IMapper _mapper;

    public TruckService(IAppRepository appRepository, IMapper mapper)
    {
        _appRepository = appRepository;
        _mapper = mapper;
    }
 }

I would like to use like this.我想这样使用。 But I'm getting an exception when the Mapper.AssertConfigurationIsValid();但是我在Mapper.AssertConfigurationIsValid();时遇到了一个异常Mapper.AssertConfigurationIsValid(); line runs, saying that:行运行,说:

'Mapper not initialized. '映射器未初始化。 Call Initialize with appropriate configuration.使用适当的配置调用 Initialize。 If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.'如果您尝试通过容器或其他方式使用映射器实例,请确保您没有对静态 Mapper.Map 方法的任何调用,并且如果您使用的是 ProjectTo 或 UseAsDataSource 扩展方法,请确保您传入适当的 IConfigurationProvider实例。'

What am I missing here?我在这里缺少什么? The problem seems to be in the Mapper.Map<IEnumerable<App>, List<App>>(src.ToList()) line of code.问题似乎出在Mapper.Map<IEnumerable<App>, List<App>>(src.ToList())代码行中。

But how can I get an instance of the Mapper there without using the static Mapper ?但是如何在不使用静态Mapper的情况下获得Mapper的实例?

Try using AddAutoMapper from AutoMapper.Extensions.Microsoft.DependencyInjection which you can add as a NuGet package.尝试使用AutoMapper.Extensions.Microsoft.DependencyInjection中的AddAutoMapper ,您可以将其添加为 NuGet 包。

So, you'd completely remove the MappingServiceExtension class, and then in Startup.cs add these two lines:因此,您将完全删除MappingServiceExtension类,然后在 Startup.cs 中添加以下两行:

AutoMapper.Mapper.Reset();
services.AddAutoMapper(typeof(ApplicationMapping).Assembly);

I forgot the exact reason, but when using AutoMapper in across multiple projects/assemblies, you need to register it for DI this way.我忘记了确切的原因,但是在跨多个项目/程序集使用 AutoMapper 时,您需要以这种方式为 DI 注册它。 Read more here .在这里阅读更多。

Mapper.AssertConfigurationIsValid();

This calls the static IMapper instance which is used in situations where you don't use dependency injection.这将调用静态IMapper实例,该实例在您不使用依赖注入的情况下使用。 Since you never set up the static mapper, using it there will fail.由于您从未设置过静态映射器,因此在那里使用它会失败。

What you want to do instead is call AssertConfigurationIsValid on the actual mapper instance, the one that you are registering as a singleton.您想要做的是在实际映射器实例上调用AssertConfigurationIsValid ,该实例是您注册为单例的。 So you should remove the assert from the mapper profile and instead call it within your AddApplicationMappings method:所以你应该从映射器配置文件中删除断言,而是在你的AddApplicationMappings方法中调用它:

IMapper mapper = mapperConfig.CreateMapper();
mapper.AssertConfigurationIsValid();
services.AddSingleton(mapper);

Similar to what @johnluke.laue suggested.类似于@johnluke.laue 的建议。 In AddApplicationMappings simply replace the code with the following:AddApplicationMappings只需将代码替换为以下内容:

services.AddAutoMapper(config =>
{
    config.AddProfile<ApplicationMapping>();
});

The above will automatically add the IMapper to the DI.以上将自动将IMapper添加到 DI。 In addition, modify the RegisterMappings function as below.另外,修改RegisterMappings函数如下。 You don't need to explicitly map the IEnumerable<T> .您不需要显式映射IEnumerable<T> It will be mapped implicitly if the source/destination mappings exist.如果源/目标映射存在,它将被隐式映射。

private void RegisterMappings()
{
   CreateMap<IEnumerable<App>, ListAppsDto>()
       .ForMember(dest => dest.Apps, opt => opt.MapFrom(src => src.ToList());
}

It would be helpful to see the actual App and ListAppDto classes, as you don't explicitly need the above mappings.查看实际的AppListAppDto类会很有帮助,因为您并不明确需要上述映射。 I hope this helps我希望这有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM