欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

在ABP中灵活使用AutoMapper

程序员文章站 2022-04-29 14:24:46
demo地址: "ABP.WindowsService" 该文章是系列文章 "基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业" 的其中一篇。 AutoMapper简介 AutoMapper是一个简单的小型的对象映射库,是为了解决一个繁杂的问题 将一个对象映射到另一个 ......

demo地址:abp.windowsservice
该文章是系列文章 基于.netcore和abp框架如何让windows服务执行quartz定时作业 的其中一篇。

automapper简介

automapper是一个简单的小型的对象映射库,是为了解决一个繁杂的问题 - 将一个对象映射到另一个对象的到处乱飞的胶水代码。这类胶水代码非常沉闷,让人怀疑自己的工作的价值性。automapper就是你摆脱此类代码的福音。
官网地址:
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的全部内容,谢谢阅读。