zoukankan      html  css  js  c++  java
  • ASP.NET Core 中的对象映射之 AutoMapper

    AutoMapper 简介

    AutoMapper是一个对象映射器,它可以将一种类型的对象转换为另一种类型的对象。

    它提供了映射规则及操作方法,使我们不用过多配置就可以映射两个类, 可以帮我们免于编写无聊的映射代码. 在代码层与层之间隔离模型model上非常有用.

    AutoMapper 使用

    初始化

    创建两个简单的类用于测试:

    public class UserEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public class UserDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    AutoMapper可以使用静态类和实例方法来创建映射.

    • 静态类方式

      Mapper.Initialize(cfg => cfg.CreateMap<UserEntity, UserDTO>());
      var userDTO = Mapper.Map<UserDTO>(user);
      
    • 实例方式

      var config = new MapperConfiguration(cfg => cfg.CreateMap<UserEntity, UserDTO>());
      var mapper = config.CreateMapper();
      
      var userDTO = mapper.Map<UserDTO>(user);
      
    • 依赖注入

      使用扩展 AutoMapper.Extensions.Microsoft.DependencyInjection 来实现AutoMapper的依赖注入. 本质是注册一个MapperConfiguration的单例和IMapper的scope实例, 通过程序集扫描添加AutoMapper的相关配置和映射.

      IServiceCollection services = new ServiceCollection();
      services.AddAutoMapper();
      
      var provider = services.BuildServiceProvider();
      using (var scope = provider.CreateScope())
      {
          var mapper = scope.ServiceProvider.GetService<IMapper>();
          var userDTO = mapper.Map<UserDTO>(user);
      }
      

    Profile设置

    可以使用Profie配置来实现映射关系, 然后通过AddProfile添加.

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>();
        }
    }
    
    var config = new MapperConfiguration(cfg => cfg.AddProfile<UserProfile>());
    

    扁平化映射

    AutoMapper支持扁平化映射, 它会根据Pascal命名方式分割目标字段为单个单词, 可自动映射属性名+内嵌属性名. 如下例AutoMapper自动映射UserEntity.Address.City -> UserDTO.AddressCity。

    public class UserEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public Address Address { get; set; }
    }
    
    public class Address
    {
        public string City { get; set; }
        public string Country { get; set; }
    }
    
    public class UserDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string AddressCity { get; set; }
        public string AddressCountry { get; set; }
    }
    

    集合映射

    AutoMapper除了可以映射单个对象外,也可以映射集合对象。

    CreateMap<UserEntity, UserDTO>();
    
    var userList = new List<UserEntity> {
        new UserEntity { Id = 1, Name="Test1" },
        new UserEntity { Id = 2, Name="Test2" },
    };
    var dtoList = mapper.Map<List<UserDTO>>(userList);
    
    public class UserEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public List<AddressEntity> AddressList { get; set; }
    }
    
    public class AddressEntity
    {
        public string City { get; set; }
        public string Country { get; set; }
    }
    
    public class UserDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public List<AddressDTO> AddressList { get; set; }
    }
    
    public class AddressDTO
    {
        public string City { get; set; }
        public string Country { get; set; }
    }
    
    CreateMap<AddressEntity, AddressDTO>();
    CreateMap<UserEntity, UserDTO>();
    
    var user = new UserEntity
    {
        Id = 1,
        Name = "Test",
        AddressList = new List<AddressEntity>
        {
            new AddressEntity { City = "ShangHai", Country = "China"},
            new AddressEntity { City = "BeiJing", Country = "China"}
        }
    };
    
    var userDTO = mapper.Map<UserDTO>(user);
    

    投影

    当把一个源值投影到一个不精准匹配源结构的目标值时,使用MapFrom指明成员映射定义。

    public class UserEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }
    }
    
    public class UserDTO
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string BirthYear { get; set; }
        public string BirthMonth { get; set; }
    }
    
    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ForMember(d => d.BirthYear, o => o.MapFrom(s => s.BirthDate.Year))
                .ForMember(d => d.BirthMonth, o => o.MapFrom(s => s.BirthDate.Month));
        }
    }
    
    var user = new UserEntity
    {
        Id = 1,
        Name = "Test",
        BirthDate = DateTime.Today,
    };
    
    var userDTO = mapper.Map<UserDTO>(user);
    

    条件映射

    有些情况下,我们将只满足映射条件的才添加到属性上.

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ForMember(d => d.Id, o => o.Condition(s => s.Id > 1));
        }
    }
    

    值转换

    AutoMapper可以配置值转换和空值替换

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ForMember(d => d.Name, o => o.NullSubstitute("Default Name"))
                .ForMember(d => d.Name, o => o.AddTransform(val => string.Format("Name: {0}", val)));
        }
    }
    

    设置转换前后行为

    有时候,在映射发生之前或之后,可能需要执行一些自定义的逻辑。

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .BeforeMap((s, d) => s.BirthDate = s.BirthDate.AddYears(-12))
                .AfterMap((s, d) => d.BirthMonth = "July");
        }
    }
    

    配置验证及设置

    配置了映射,但是如何确定是否映射成功或者是否有字段没有映射呢?可以使用mapper.ConfigurationProvider.AssertConfigurationIsValid()来验证是否映射成功。但也可以指定单个字段不验证.

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ForMember(d => d.NickName, o => o.Ignore());
        }
    }
    

    反向映射

    从6.1.0开始,AutoMapper通过ReverseMap可以实现反向映射。使用ReverseMap, 不用再创建DTO -> Entity的映射, 而且还能保留正向的映射规则。

    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ReverseMap();
        }
    }
    

    自定义转换器

    有些情况下目标字段类型和源字段类型不一致,可以通过类型转换器实现映射,类型转换器有三种实现方式:

    void ConvertUsing(Func<TSource, TDestination> mappingFunction);
    void ConvertUsing(ITypeConverter<TSource, TDestination> converter);
    void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>;
    

    自定义解析器

    某些情况下,解析规则会很复杂,使用自带的解析规则无法实现。这时可以自定义解析规则,可以通过以下三种方式使用自定义的解析器:

    ResolveUsing<TValueResolver>
    ResolveUsing(typeof(CustomValueResolver))
    ResolveUsing(aValueResolverInstance)
    
    public class UserEntity
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
    public class UserDTO
    {
        public string Name { get; set; }
    }
    
    public class UserNameResolver : IValueResolver<UserEntity, UserDTO, string>
    {
        public string Resolve(UserEntity source, UserDTO destination, string destMember, ResolutionContext context)
        {
            if (source != null && !string.IsNullOrEmpty(source.FirstName) && !string.IsNullOrEmpty(source.LastName))
            {
                return string.Format("{0} {1}", source.FirstName, source.LastName);
            }
    
            return string.Empty;
        }
    }
    
    public class UserProfile : Profile
    {
        public UserProfile()
        {
            CreateMap<UserEntity, UserDTO>()
                .ForMember(d => d.Name, o => o.ResolveUsing<UserNameResolver>());
        }
    }
    

    参考

  • 相关阅读:
    mysql关联更新表
    List Slider
    mysql同步复制报Slave can not handle replication events with the checksum that master 错误
    ie11 .pac代理脚本无法使用的问题2
    centos6.5安装配置nginx+php+mysql+httpsqs+ttserver+redis
    Linux 磁盘坏道检测和修复
    ie11 .pac代理脚本无法使用的问题
    javascript取前n天的日期两种方法
    javascript位操作符右移>>>的妙用
    Angular表单验证
  • 原文地址:https://www.cnblogs.com/royzshare/p/9951683.html
Copyright © 2011-2022 走看看