AutoMapper从静态API迁移

时间:2016-02-07 16:29:36

标签: c# asp.net automapper

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>();
        });
    }
}

===&GT; AbcMappingProfile.cs

public class AbcMappingProfile : Profile
{
    protected override void Configure()
    {
        Mapper.CreateMap<AbcEditViewModel, Abc>();
        Mapper.CreateMap<Abc, AbcEditViewModel>();
        ...
    }
}

ERROR:

'Mapper.CreateMap()'已过时:'将在5.0版中删除静态API。使用MapperConfiguration实例并根据需要静态存储。使用CreateMapper创建映射器实例。'

我可以使用Mapper.Map。现在我该怎么用呢

4 个答案:

答案 0 :(得分:43)

而不是:

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);

Source with more examples

答案 1 :(得分:9)

使用IMapperConfigurationExpression扩展名代替Automapper Profile:

映射配置:

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());

答案 2 :(得分:1)

依赖注入给我原来不想处理的遗留项目增加了一个整体的复杂性。由于使用许多不同的技术,Webforms,MVC,Azure Service等来调用同一个库,所以...

依赖注入还会迫使我重写几种方法或传递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);

答案 3 :(得分:0)

  本·沃尔特斯(Ben Walters):依赖注入使整体复杂性增加了   我不想处理的遗留项目...

HI

此外,您可以使用语句应用类别名 无需更改代码,只需更改using语句即可。

为一个类定义一个using指令和一个using别名: https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/using-directive#example-2

-

。您的类实现具有兼容性。

namespace AutoMappers
{
  public class Mapper
  {
    public static void Initialize(Action<AutoMapper.IMapperConfigurationExpression> config)
    {
      ...
    }
  }
}

。将“使用AutoMapper”更改为“使用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

-