zoukankan      html  css  js  c++  java
  • 在ABP中灵活使用AutoMapper

    demo地址:ABP.WindowsService
    该文章是系列文章 基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业 的其中一篇。

    AutoMapper简介

    AutoMapper是一个简单的小型的对象映射库,是为了解决一个繁杂的问题 - 将一个对象映射到另一个对象的到处乱飞的胶水代码。这类胶水代码非常沉闷,让人怀疑自己的工作的价值性。AutoMapper就是你摆脱此类代码的福音。
    官网地址:https://automapper.org/
    GitHub地址:https://github.com/AutoMapper/AutoMapper

    AutoMapper的简单使用

    这里拿官网的例子做一个简单说明,主要是为了引出在Abp中是如何使用的,来进行对比。使用AutoMapper将遇到的最经典的两个场景。

    1. 最多遇到的场景,应该是接口返回的DTO和数据库Entity,出于敏感信息保护或者减少接口返回数据等等的原因,DTO返回的属性或者字段有所删减,也就是说需要映射的属性或者字段属性名称一致。
    2. DTO和Entity名称不一致,甚至类型不同,相互转换时甚至需要对数据有处理。

    下面的例子就是字段属性基本一致。

    public class Order
    {
    		public string OrderName { get;set; }
    		public string PhoneNumber { get;set; }
    }
    public class OrderDto
    {
    		public string OrderName { get;set; }
    }
    
    var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());
    var mapper = config.CreateMapper();
    OrderDto dto = mapper.Map<OrderDto>(order);
    

    或者

    var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());
    var mapper = new Mapper(config);
    OrderDto dto = mapper.Map<OrderDto>(order);
    

    Abp.AutoMapper的简单使用

    Abp.AutoMapper的官网文档:https://aspnetboilerplate.com/Pages/Documents/Object-To-Object-Mapping
    Abp.AutoMapper的Nuget地址:https://www.nuget.org/packages/Abp.AutoMapper

    添加nuget包

    Install-Package Abp.AutoMapper
    

    添加AbpAutoMapperModule模块

    [DependsOn(typeof(AbpAutoMapperModule))]
    public class MyJobCoreModule : AbpModule
    {
    }
    

    指定映射关系

    自动映射

    你可以通过属性AutoMap, AutoMapFrom, AutoMapTo指定映射关系
    改造上面的之前的例子

    [AutoMapFrom(typeof(Order))]
    public class OrderDto
    {
    		public string OrderName { get;set; }
    }
    

    或者

    [AutoMapTo(typeof(OrderDto))]
    public class Order
    {
    		public string OrderName { get;set; }
    		public string PhoneNumber { get;set; }
    }
    

    但是属性的使用场景比较窄,稍微复杂一点的场景就无法满足,比如,指定忽略一些字段,或者字段名称不同需要显示指定。

    自定义映射

    [DependsOn(typeof(AbpAutoMapperModule))]
    public class MyJobCoreModule : AbpModule
    {
        public override void PreInitialize()
        {
            Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
            {
                config.CreateMap<Order, OrderDto>();
            });
        }
    }
    

    忽略字段

    config.CreateMap<Order, OrderDto>()
    		  .ForMember(u => u.PhoneNumber, options => options.Ignore());
    

    字段名不一致

    OrderDto增加手机号字段Tel,映射Order字段PhoneNumber

        public class OrderDto
        {
            public string OrderName { get; set; }
            public string Tel { get; set; }
        }
    
    config.CreateMap<Order, OrderDto>()
    		  .ForMember(u => u.Tel, options => options.MapFrom(input => input.PhoneNumber));
    

    需要对字段进行处理后返回

    比如,隐藏11位手机号的中间4位

    private static string HideTel(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return string.Empty;
        }
        var outReplace = Regex.Replace(input, "(\d{3})\d{4}(\d{4})", "$1****$2");
        return outReplace;
    }
    
    config.CreateMap<Order, OrderDto>()
    		  .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.PhoneNumber)));
    

    拼接映射

    又比如OrderDto新增邮寄地址和收货地址

    namespace Demo.MyJob.Entity.Dto
    {
        public class OrderDto
        {
            public string OrderName { get; set; }
            public string Tel { get; set; }
            public string PostalAddress { get; set; }
            public string DeliveryAddress { get; set; }
        }
    }
    

    Order的相关表OrderAddress类型定义

    namespace Demo.MyJob.Entity
    {
        public class OrderAddress
        {
            public string OrderId { get; set; }
            public string PostalAddress { get; set; }
            public string DeliveryAddress { get; set; }
        }
    }
    

    这时就需要OrderAddress和Order的数据相结合映射OrderDto,怎么实现呢?借助元组Tuple。

    config.CreateMap<(Order, OrderAddress), OrderDto>()
    		  .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
    		  .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
    		  .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
    		  .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
    		  ;
    

    精简配置

    需要自定义的映射关系过多时,会使得PreInitialize变大,不便于管理和查看。

    public override void PreInitialize()
    {
        Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
        {
            config.CreateMap<(Order, OrderAddress), OrderDto>()
    		  .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
    		  .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
    		  .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
    		  .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
    		  ;
        });
    }
    

    如何精简?新增类型MyMapperProfile,继承AutoMapper.Profile

    using System.Text.RegularExpressions;
    using AutoMapper;
    using Demo.MyJob.Entity;
    using Demo.MyJob.Entity.Dto;
    
    namespace Demo.MyJob.MapperProfiles
    {
        class MyMapperProfile : Profile
        {
            private static string HideTel(string input)
            {
                if (string.IsNullOrEmpty(input))
                {
                    return string.Empty;
                }
                var outReplace = Regex.Replace(input, "(\d{3})\d{4}(\d{4})", "$1****$2");
                return outReplace;
            }
            public MyMapperProfile()
            {
                CreateMap<Order, OrderDto>()
                    .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.PhoneNumber)));
    
                CreateMap<(Order, OrderAddress), OrderDto>()
                    .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
                    .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
                    .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
                    .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
                    ;
            }
        }
    }
    
    

    修改PreInitialize

    [DependsOn(typeof(AbpAutoMapperModule))]
    public class MyJobCoreModule : AbpModule
    {
        public override void PreInitialize()
        {
            Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
            {
                config.AddMaps(typeof(MyJobCoreModule));
            });
        }
    }
    

    Abp.AutoMapper版本低于4.8.0的可以修改为

    config.AddProfiles(typeof(MyJobCoreModule));
    

    以上就是如何在Abp框架下灵活使用AutoMapper的全部内容,谢谢阅读。

  • 相关阅读:
    Sqlserver 2008:sp_msforeachdb 坑爹的错误陷阱
    安装官方 Synaptics 驱动,终于解决 HP Pavilion G4 笔记本 讨厌的触摸板锁定问题!
    Sqlserver 2008+:变更数据捕获(CDC) 和 更改跟踪(CT)
    PHP.ini 性能优化
    PHP Notice: Undefined index: ... 问题的解决方案
    查询类方法代码分析
    页面跳转方法总结大全
    如何关闭searchIndexer.exe进程
    如何正确运用PHP ini_set函数
    PHP中的串行化变量和序列化对象
  • 原文地址:https://www.cnblogs.com/AlienXu/p/Abp_AutoMapper.html
Copyright © 2011-2022 走看看