Automapper говорит, что Mapper.Map устарел, глобальные сопоставления?

Я определил в своем проекте глобальную конфигурацию Automapper, которая позволит мне использовать Mapper.Map<targetType>(sourceObject); в моем коде. (См. Мою конфигурацию ниже.)

Я обновил пакет NuGet и вижу сообщение о том, что Mapper.Map устарел / устарел. Я вернулся к Automapper на GitHub и увидел примеры, подобные этому:

[Test]
public void Example()
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Source1, SubDest1>().FixRootDest();
        cfg.CreateMap<Source2, SubDest2>().FixRootDest();
    });

    config.AssertConfigurationIsValid();

    var mapper = config.CreateMapper();

    var subDest1 = mapper.Map<Source1, SubDest1>(new Source1 {SomeValue = "Value1"});
    var subDest2 = mapper.Map<Source2, SubDest2>(new Source2 {SomeOtherValue = "Value2"});

    subDest1.SomeValue.ShouldEqual("Value1");
    subDest2.SomeOtherValue.ShouldEqual("Value2");
}

Я собираюсь создать конфигурацию в КАЖДОМ методе, который использует сопоставление?

Моя текущая глобальная конфигурация:

namespace PublicationSystem.App_Start
{
    public class AutoMapperConfig
    {
        public static void CreateMaps()
        {
            CreateProjectMaps();
        }

        private static void CreateProjectMaps()
        {
            Mapper.CreateMap<Project, ProjectCreate>();
            Mapper.CreateMap<Project, ProjectSelectable>();
            //...
        }
    }
}

ОБНОВЛЕНИЕ: Благодаря некоторому обучению от Скотта Чемберлена я создал класс как это:

    public class MkpMapperProfile : AutoMapper.Profile
    {
        protected override void Configure() 
        {
            this.CreateMap<Project, ProjectCreate>();

            this.CreateMap<Project, ProjectSelectable>();

            this.CreateMap<Project, ProjectDetails>();

            // Many Many other maps
        }
    }

Я думаю, что у меня должен быть 'MapperConfiguration' в моем классе BaseController. Я начал делать что-то вроде этого:

public partial class BaseController : Controller
{

    private MapperConfiguration mapConfig;

    public BaseController()
    {
        db = new MkpContext();
        SetMapperConfig();
    }

    private void SetMapperConfig()
    {
        mapConfig = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile<MkpMapperProfile>();
            });
    }

    public BaseController(MapperConfiguration config)
    {
        db = new MkpContext();
        this.mapConfig = config;
    }
}

Я на правильном пути?

5 ответов

Решение

Вот как я справился с этим.

Создайте карты в профиле, стараясь использовать метод CreateMap профиля, а не статический метод Mapper с тем же именем:

internal class MappingProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<Project, ProjectCreate>();
    }
}

Затем, где бы ни были связаны зависимости (например, Global.asax или Startup), создайте MapperConfiguration, а затем используйте его для создания IMapper.

var mapperConfiguration = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile(new MappingProfile());
    });

Затем используйте конфигурацию для генерации IMapper:

var mapper = mapperConfiguration.CreateMapper();

Затем зарегистрируйте этот маппер в построителе зависимостей (здесь я использую Autofac)

builder.RegisterInstance(mapper).As<IMapper>();

Теперь, где вам нужно отобразить материал, объявите зависимость от IMapper:

internal class ProjectService : IProjectService {
    private readonly IMapper _mapper;
    public ProjectService(IMapper mapper) {
         _mapper = mapper;
    }
    public ProjectCreate Get(string key) {
        var project = GetProjectSomehow(key);
        return _mapper.Map<Project, ProjectCreate>(project);
    }
}

Я использую версию 5.2.0, поддержку для создания карт в конструкторах вместо переопределения конфигурации.

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Project, ProjectDto>();
    }
}

В Global.asax.cs звоните так:

Mapper.Initialize(c=>c.AddProfile<MappingProfile>());

Надеюсь, это поможет.

Это новое в AutoMapper 4.2. Джимми Богард пишет в блоге об этом: удаление статического API из AutoMapper. Он утверждает, что

Интерфейс IMapper намного легче, и базовый тип теперь просто связан с выполнением карт, устраняя множество проблем с многопоточностью...

Новый синтаксис: (вставлено из поста в блоге)

var config = new MapperConfiguration(cfg => {
  cfg.CreateMap<User, UserDto>();
});

Если вы просто хотите "старый способ" сделать это. Последняя версия 4.2.1 вернула некоторые традиции. Просто используйте

CreateMap<Project, ProjectCreate>();

вместо

Mapper.CreateMap<Project, ProjectCreate>();

Старый код будет работать нормально.

Вы можете найти настроенный AutoMapper 4.2 в моем проекте ASP.NET MVC Template здесь: https://github.com/NikolayIT/ASP.NET-MVC-Template

  1. Создайте эти классы: https://github.com/NikolayIT/ASP.NET-MVC-Template/tree/master/ASP.NET%20MVC%205/Web/MvcTemplate.Web.Infrastructure/Mapping

  2. Аннотировать вид моделей с IMapFrom<>: https://github.com/NikolayIT/ASP.NET-MVC-Template/blob/master/ASP.NET%20Core/Web/AspNetCoreTemplate.Web/ViewModels/Settings/SettingViewModel.cs

  3. Используйте это как .To<SomeViewModel>(), Пример: https://github.com/NikolayIT/ASP.NET-MVC-Template/blob/master/ASP.NET%20MVC%205/Web/MvcTemplate.Web/Controllers/HomeController.cs#L27

Mapper.Initialize(cfg => {
    cfg.CreateMap<Source, Dest>();
});
Другие вопросы по тегам