【问题标题】:Using Automapper with ASP.NET Core将 Automapper 与 ASP.NET Core 一起使用
【发布时间】:2019-10-07 05:51:49
【问题描述】:

我正在尝试在 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())
                           )
                      );
    }
}

这个类在我的Application dll 中,我在其中放置了我的服务和 DTO。同样在这个 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);
    }
}

然后在我的 WebAPI 项目中,在我放的 Startup.cs 类上:

  services.AddApplicationMappings();

我通常在我的服务中将它与 DI 一起使用:

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

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

我想这样使用。但是当Mapper.AssertConfigurationIsValid(); 行运行时我遇到了一个异常,说:

'映射器未初始化。使用适当的配置调用初始化。如果您尝试通过容器或其他方式使用映射器实例,请确保您没有对静态 Mapper.Map 方法的任何调用,并且如果您使用 ProjectTo 或 UseAsDataSource 扩展方法,请确保传入适当的 IConfigurationProvider实例。'

我在这里缺少什么?问题似乎出在Mapper.Map&lt;IEnumerable&lt;App&gt;, List&lt;App&gt;&gt;(src.ToList()) 代码行。

但是如何在不使用静态 Mapper 的情况下获得 Mapper 的实例?

【问题讨论】:

  • 你需要 Custom type converter 来代替 IEnumerable&lt;App&gt;, List&lt;App&gt; 并从 ResolutionContext 获取 mapper
  • 它没有解决问题,因为我仍然需要在 CustomTypeConverter 类上使用context.Mapper.Map&lt;...&gt;。仍然出现同样的错误。

标签: c# asp.net-core automapper


【解决方案1】:
Mapper.AssertConfigurationIsValid();

这会调用 static IMapper 实例,该实例用于不使用依赖注入的情况。由于您从未设置静态映射器,因此在那里使用它会失败。

您想要做的是在实际的映射器实例上调用AssertConfigurationIsValid,您正在注册为单例。因此,您应该从映射器配置文件中删除断言,而是在您的 AddApplicationMappings 方法中调用它:

IMapper mapper = mapperConfig.CreateMapper();
mapper.AssertConfigurationIsValid();
services.AddSingleton(mapper);
【解决方案2】:

尝试使用 AutoMapper.Extensions.Microsoft.DependencyInjection 中的 AddAutoMapper,您可以将其添加为 NuGet 包。

因此,您将完全删除 MappingServiceExtension 类,然后在 Startup.cs 中添加这两行:

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

我忘记了确切的原因,但是在跨多个项目/程序集使用 AutoMapper 时,您需要以这种方式为 DI 注册它。阅读更多here

【讨论】:

  • 如果您喜欢像 OP 那样使用显式映射配置,则不需要 AutoMapper.Extensions.Microsoft.DependencyInjection。该软件包主要用于自动发现映射配置文件。
【解决方案3】:

类似于@johnluke.laue 的建议。在AddApplicationMappings 中,只需将代码替换为以下内容:

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

上面会自动将IMapper添加到DI。另外,修改RegisterMappings函数如下。您不需要显式映射IEnumerable&lt;T&gt;。如果源/目标映射存在,它将被隐式映射。

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

查看实际的AppListAppDto 类会很有帮助,因为您并不明确需要上述映射。我希望这会有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2017-03-11
    • 2019-11-02
    相关资源
    最近更新 更多