Ошибка Automapper, говорящая, что mapper не инициализирован

Я использую Automapper 5.2. Я использовал в качестве основы эту ссылку. Я опишу, поэтапно, процесс настройки Automapper, через который я прошел.

Первый Я добавил Automapper в Project.json, как указано:

PM> Install-Package AutoMapper

Второй Я создал папку для хранения всех файлов, относящихся к сопоставлению, называемых "Сопоставление"

Третий Я установил конфигурацию Automapper в своем собственном файле в папке сопоставлений:

public class AutoMapperConfiguration
{
    public MapperConfiguration Configure()
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile<ViewModelToDomainMappingProfile>();
            cfg.AddProfile<DomainToViewModelMappingProfile>();
            cfg.AddProfile<BiDirectionalViewModelDomain>();
        });
        return config;
    }
}

Forth Также в своем собственном файле в папке сопоставлений я настроил профиль отображения следующим образом:

public class DomainToViewModelMappingProfile : Profile
{
    public DomainToViewModelMappingProfile()
    {
        CreateMap<Client, ClientViewModel>()
           .ForMember(vm => vm.Creator, map => map.MapFrom(s => s.Creator.Username))
           .ForMember(vm => vm.Jobs, map => map.MapFrom(s => s.Jobs.Select(a => a.ClientId)));
    }
}

Пятый, я добавил метод расширения как свой собственный файл также в папку сопоставлений... это было использовано далее в startup.cs:

public static class CustomMvcServiceCollectionExtensions
{
    public static void AddAutoMapper(this IServiceCollection services)
    {
        if (services == null)
        {
            throw new ArgumentNullException(nameof(services));
        }
        var config = new AutoMapperConfiguration().Configure();
        services.AddSingleton<IMapper>(sp => config.CreateMapper());
    }
}

Шестой Я добавил эту строку в метод ConfigureServices в Startup.cs

        // Automapper Configuration
        services.AddAutoMapper();

Наконец, я использовал его в контроллере для преобразования коллекции...

 IEnumerable<ClientViewModel> _clientVM = Mapper.Map<IEnumerable<Client>, IEnumerable<ClientViewModel>>(_clients);

Основываясь на вопросе, о котором я говорил ранее, я думал, что у меня есть все, чтобы использовать его, но я получил ошибку на строке выше в контроллере...

"Mapper не инициализирован. Инициализация вызова с соответствующей конфигурацией. Если вы пытаетесь использовать экземпляры mapper через контейнер или иным образом, убедитесь, что у вас нет вызовов статических методов Mapper.Map, и если вы используете ProjectTo или UseAsDataSource, убедитесь, что вы передали соответствующий экземпляр IConfigurationProvider."

Что я пропустил.. Правильно ли это настроить Automapper? Я подозреваю, что мне не хватает шага здесь. Любая помощь очень ценится.

Ответ 1

AutoMapper имеет два варианта использования: вложение зависимостей и старое статическое для обратной совместимости. Вы настраиваете его для инъекции зависимостей, но затем пытаетесь использовать статический. Это ваша проблема. Вам просто нужно выбрать один или другой метод и пойти с ним.

Если вы хотите сделать это с помощью инъекции зависимостей, ваш контроллер должен взять mapper в качестве аргумента конструктора, сохраняя его для члена, а затем вам нужно будет использовать этот элемент для выполнения вашего сопоставления:

public class FooController : Controller
{
    private readonly IMapper mapper;

    public FooController(IMapper mapper)
    {
        this.mapper = mapper;
    }

Тогда:

IEnumerable<ClientViewModel> _clientVM = mapper.Map<IEnumerable<Client>, IEnumerable<ClientViewModel>>(_clients);

Для статического метода вам необходимо инициализировать AutoMapper с помощью вашей конфигурации:

public MapperConfiguration Configure()
{
    AutoMapper.Mapper.Initialize(cfg =>
    {
        cfg.AddProfile<ViewModelToDomainMappingProfile>();
        cfg.AddProfile<DomainToViewModelMappingProfile>();
        cfg.AddProfile<BiDirectionalViewModelDomain>();
    });
}

Затем вам нужно вызвать этот метод только в Startup.cs; вы больше не будете регистрировать синглтон.