Использование Automapper с ASP.NET Core - PullRequest
1 голос
/ 20 мая 2019

Я пытаюсь использовать Automapper с конфигурацией Dependency Injection для n-слойного приложения.

 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 не инициализирован.Вызовите Initialize с соответствующей конфигурацией.Если вы пытаетесь использовать экземпляры mapper через контейнер или иным образом, убедитесь, что у вас нет вызовов статических методов Mapper.Map, и если вы используете методы расширения ProjectTo или UseAsDataSource, убедитесь, что вы передаете соответствующий IConfigurationProvider.экземпляр. '

Что мне здесь не хватает?Кажется, проблема в строке кода Mapper.Map<IEnumerable<App>, List<App>>(src.ToList()).

Но как я могу получить экземпляр Mapper там без использования статического Mapper?

Ответы [ 3 ]

1 голос
/ 21 мая 2019
Mapper.AssertConfigurationIsValid();

Это вызывает статический IMapper экземпляр, который используется в ситуациях, когда вы не используете внедрение зависимостей. Поскольку вы никогда не устанавливали статический маппер, его использование не удастся.

Вместо этого вы хотите вызвать AssertConfigurationIsValid на фактическом экземпляре mapper, который вы регистрируете как одиночный. Поэтому вы должны удалить assert из профиля mapper и вместо этого вызвать его в вашем AddApplicationMappings методе:

IMapper mapper = mapperConfig.CreateMapper();
mapper.AssertConfigurationIsValid();
services.AddSingleton(mapper);
1 голос
/ 21 мая 2019

Попробуйте использовать AddAutoMapper из AutoMapper.Extensions.Microsoft.DependencyInjection, который вы можете добавить как пакет NuGet.

Итак, вы полностью удалите класс MappingServiceExtension, а затем в Startup.cs добавите две строки:

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

Я забыл точную причину, но при использовании AutoMapper для нескольких проектов / сборок вам необходимо зарегистрировать его для DI таким образом. Подробнее здесь .

0 голосов
/ 21 мая 2019

Похоже на то, что предложил @ johnluke.laue.В AddApplicationMappings просто замените код следующим:

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

Выше автоматически добавит IMapper к DI.Кроме того, измените функцию RegisterMappings, как показано ниже.Вам не нужно явно отображать IEnumerable<T>.Он будет отображаться неявно, если существуют сопоставления источника / назначения.

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

Было бы полезно увидеть фактические классы App и ListAppDto, поскольку вам явно не нужны вышеуказанные сопоставления.Я надеюсь, что это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...