AutoMapper Migrating from static API

后端 未结 4 1639
无人及你
无人及你 2020-12-05 05:08

https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API

this change breaks my system.

Before update, I use:

===> Startup.cs



        
相关标签:
4条回答
  • 2020-12-05 05:15

    Instead of Automapper Profile use IMapperConfigurationExpression extension:

    Mapping configuration:

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

    Integration (Startup.cs etc.):

            var mappingConfig = new AutoMapper.MapperConfiguration(cfg =>
            {
                cfg.AddAdminMapping();
            });
    
            services.AddSingleton(x => mappingConfig.CreateMapper());
    
    0 讨论(0)
  • 2020-12-05 05:18

    Instead of:

    Mapper.CreateMap<AbcEditViewModel, Abc>();
    

    The new syntax is:

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

    Then:

    IMapper mapper = config.CreateMapper();
    var source = new AbcEditViewModel();
    var dest = mapper.Map<AbcEditViewModel, Abct>(source);
    

    (Source with more examples)

    0 讨论(0)
  • 2020-12-05 05:25

    Ben Walters: Dependency injection added a whole level of complexity to my legacy project that I just didn't want to deal with...

    HI

    Furthermore, you can apply the class alias using statement and no need to change the code, just change the using statement.

    Define a using directive and a using alias for a class: https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/using-directive#example-2

    --

    .Your class implementation for compatibility.

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

    .Change "using AutoMapper" to "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

    --

    0 讨论(0)
  • 2020-12-05 05:30

    Dependency injection added a whole level of complexity to my legacy project that I just didn't want to deal with. As the same library is called with many different technologies, Webforms, MVC, Azure Service, etc...

    Also dependency injection would of forced me to rewrite several methods or pass an IMapper around.

    So I just reverse engineered what it was doing in 8.0 and wrote a wrapper for it.

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

    Initialize it just like you did in previous versions

    public static class AutoMapperConfig
    {
        public static void Configure()
        {
            MapperWrapper.Initialize(cfg =>
            {
                cfg.CreateMap<Foo1, Foo2>();              
            });
    
            MapperWrapper.AssertConfigurationIsValid();
        }
    }
    

    And just call it in your startup, (Global.asax etc..)

    AutoMapperConfig.Configure();
    

    Then all you have to do is add MapperWrapper before all your static calls. And everything works as it did before.

     MapperWrapper.Mapper.Map<Foo2>(Foo1);
    
    0 讨论(0)
提交回复
热议问题