AutoMapper с DI: Не удается создать экземпляр типа… При использовании решателя значений

#c# #.net-core #automapper

Вопрос:

У меня есть API .NET Core 3.1 со следующими пакетами Nuget:

  • Автомат (10.1.1)
  • Автомат.Расширения.Майкрософт.Зависимость от инъекции (8.1.1)

Я пытаюсь сопоставить значение из сущности в dto с помощью решателя значений, и у меня есть исключение:

Исключение AutoMapperMappingException: Не удается создать экземпляр типа TestAutomapperResolver.Mapping.Пользовательское решение

Startup.cs

 public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddAutoMapper(cfg => cfg.AddMaps(typeof(TestProfile).Assembly));
}
 

TestProfile.cs

 public class TestProfile : Profile
{
    public TestProfile()
    {
        CreateMap<TestEntity, TestDto>()
            .ForMember(src => src.PropertyToBeMappedByResolver, opts => opts.MapFrom<CustomResolver>());
    }
}

public class CustomResolver : IValueResolver<TestEntity, TestDto, string>
{
    public string Resolve(TestEntity source, TestDto destination, string destMember, ResolutionContext context)
    {
        return "String generated with resolver";
    }
}
 

При этом mapper.CreateMap<TestDto>(entity); я получаю это исключение.

Кстати, использовать этот распознаватель как opts => opts.MapFrom(CustomResolver()) не вариант, потому что я хочу внедрить в этот распознаватель какую-то услугу.

Есть идеи?

Комментарии:

1. docs.automapper.org/en/latest/…

2. @LucianBargaoanu Я, очевидно, прочитал это. Я что-то упускаю?

3. Нет, я не думаю, что ты что-то упускаешь. Мне действительно кажется, что это должно сработать, и я не уверен, почему. Я привел ваш код и могу подтвердить ошибку.

4. Очевидно, что ваш код совсем не похож на пример в документах, поэтому, если вы прочитали эту страницу, как получилось, что вы написали этот код? Почему? 🙂

5. @LucianBargaoanu в какой части все не так? Вы клонировали мое репо?

Ответ №1:

Ты используешь AddMaps , когда не должен. AddMaps просто добавляет профили и сопоставления, но не добавляет все дополнительные услуги, которые предоставляет пакет DI.

Это сделает все правильно:

 services.AddAutoMapper(typeof(TestProfile).Assembly);
 

Теперь AutoMapper выдает здесь очень бесполезную ошибку, но проблема связана с внедрением зависимостей Microsoft. Инспектор не знает о вашем пользовательском типе распознавателя, поэтому он даже не пытается.

Поскольку вы не использовали метод расширения пакета DI, распознаватель не добавляется в коллекцию служб. При необходимости вы можете добавить эти службы вручную:

 services.AddAutoMapper(cfg => cfg.AddMaps(typeof(TestProfile).Assembly));
services.AddTransient<CustomResolver>();
 

Комментарии:

1. Пакет AM DI уже делает это .

2. @LucianBargaoanu Я знаю, и это не работает для меня, я спрашиваю, почему…

3. Я не уверен в этом, но если этот тест проходит, то вы, должно быть, делаете что-то не так.

4. Ладно, теперь я в замешательстве. Как это не отвечает на вопрос? Если я возьму ваш образец и запущу его, я получу исключение. Если я добавлю эту вторую строку, введя CustomResolver в DI, он преобразует объект без ошибок.

5. @LucianBargaoanu проверьте мою правку. Вы правы, но он вызывал не тот метод, который, как вы думали, он вызывал.