Миграция AutoMapper из статического API
https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API
это изменение ломает мою систему.
Перед обновлением я использую:
===> Startup.cs
public class Startup
{
public Startup(IHostingEnvironment env)
{
...
MyAutoMapperConfiguration.Configure();
}
}
===> MyAutoMapperConfiguration.cs
public class MyAutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(a =>
{
a.AddProfile<AbcMappingProfile>();
a.AddProfile<XyzMappingProfile>();
a.AddProfile<QweMappingProfile>();
});
}
}
===> AbcMappingProfile.cs
public class AbcMappingProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<AbcEditViewModel, Abc>();
Mapper.CreateMap<Abc, AbcEditViewModel>();
...
}
}
ОШИБКА:
"Mapper.CreateMap()" устарел: "Статический API будет удален в версии 5.0. Используйте экземпляр MapperConfiguration и сохраняйте статически по мере необходимости. Используйте CreateMapper, чтобы создать экземпляр Mapper.'
Я могу использовать Mapper.Map. Теперь, как я могу использовать это
2 ответа
Вместо:
Mapper.CreateMap<AbcEditViewModel, Abc>();
Новый синтаксис:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<AbcEditViewModel, Abc>();
});
Затем:
IMapper mapper = config.CreateMapper();
var source = new AbcEditViewModel();
var dest = mapper.Map<AbcEditViewModel, Abct>(source);
Вместо профиля Automapper используйте расширение IMapperConfigurationExpression:
Конфигурация сопоставления:
public static class AutoMapperConfig
{
public static IMapperConfigurationExpression AddAdminMapping(
this IMapperConfigurationExpression configurationExpression)
{
configurationExpression.CreateMap<Job, JobRow>()
.ForMember(x => x.StartedOnDateTime, o => o.PreCondition(p => p.StartedOnDateTimeUtc.HasValue))
.ForMember(x => x.StartedOnDateTime, o => o.MapFrom(p => p.StartedOnDateTimeUtc.Value.DateTime.ToLocalTime()))
.ForMember(x => x.FinishedOnDateTime, o => o.PreCondition(p => p.FinishedOnDateTimeUtc.HasValue))
.ForMember(x => x.FinishedOnDateTime, o => o.MapFrom(p => p.FinishedOnDateTimeUtc.Value.DateTime.ToLocalTime()));
return configurationExpression;
}
}
Интеграция (Startup.cs и т. Д.):
var mappingConfig = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.AddAdminMapping();
});
services.AddSingleton(x => mappingConfig.CreateMapper());
Внедрение зависимостей добавило целый уровень сложности моему унаследованному проекту, с которым я просто не хотел иметь дело. Поскольку одна и та же библиотека вызывается с множеством разных технологий, веб-форм, MVC, службы Azure и т. Д.
Кроме того, инъекция зависимостей вынудила бы меня переписать несколько методов или передать IMapper.
Поэтому я просто перепроектировал то, что он делал в 8.0, и написал для него оболочку.
public static class MapperWrapper
{
private const string InvalidOperationMessage = "Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.";
private const string AlreadyInitialized = "Mapper already initialized. You must call Initialize once per application domain/process.";
private static IConfigurationProvider _configuration;
private static IMapper _instance;
private static IConfigurationProvider Configuration
{
get => _configuration ?? throw new InvalidOperationException(InvalidOperationMessage);
set => _configuration = (_configuration == null) ? value : throw new InvalidOperationException(AlreadyInitialized);
}
public static IMapper Mapper
{
get => _instance ?? throw new InvalidOperationException(InvalidOperationMessage);
private set => _instance = value;
}
public static void Initialize(Action<IMapperConfigurationExpression> config)
{
Initialize(new MapperConfiguration(config));
}
public static void Initialize(MapperConfiguration config)
{
Configuration = config;
Mapper = Configuration.CreateMapper();
}
public static void AssertConfigurationIsValid() => Configuration.AssertConfigurationIsValid();
}
Инициализируйте его так же, как и в предыдущих версиях
public static class AutoMapperConfig
{
public static void Configure()
{
MapperWrapper.Initialize(cfg =>
{
cfg.CreateMap<Foo1, Foo2>();
});
MapperWrapper.AssertConfigurationIsValid();
}
}
И просто назовите его в своем стартапе (Global.asax и т. Д.)
AutoMapperConfig.Configure();
Тогда все, что вам нужно сделать, это добавить MapperWrapper перед всеми вашими статическими вызовами. И все работает как раньше.
MapperWrapper.Mapper.Map<Foo2>(Foo1);
Бен Уолтерс: Внедрение зависимостей добавило сложности моему унаследованному проекту, с которым я просто не хотел иметь дело...
ЗДРАВСТВУЙ
Кроме того, вы можете применить псевдоним класса, используя оператор, и нет необходимости изменять код, просто измените оператор using.
Определите директиву using и псевдоним using для класса: https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/using-directive
-
.Ваш класс реализация для совместимости.
namespace AutoMappers
{
public class Mapper
{
public static void Initialize(Action<AutoMapper.IMapperConfigurationExpression> config)
{
...
}
}
}
.Измените "using AutoMapper" на "using Mapper = AutoMappers.Mapper".
using Mapper = AutoMappers.Mapper; <-- using statement changed
namespace ...
{
public class ...
{
public ...(...)
{
Mapper.Initialize(cfg => cfg.CreateMap<TSource1, TDestination1>()); <-- other code line kept originally
-