AutoMapper入门使用

在应用开发的过程中,首先要了解整个系统中各个系统的组件的作用,然后了解系统的工作流(workflow),最后需要梳理一遍数据流(dataflow),而在整理数据流的过程中,数据的转化常常是最难理解写起来相当枯燥乏味的部分,AutoMapper的功能就是实现映射一个对象到另一个对象的自动化工具,最常见的就是DTO (Data Transfer Object)与MO(ModelObject)之间的转换,这里我先介绍一下DTO与MO的关系,然后才介绍AutoMapper工具的使用。

理解DTO

以下是我总结的几个不同平台的解释:

    • 百度百科:

数据传输对象(DTO)(Data Transfer Object),是一种设计模式之间传输数据的软件应用系统。数据传输目标往往是数据访问对象从数据库中检索数据。数据传输对象与数据交互对象或数据访问对象之间的差异是一个以不具有任何行为除了存储和检索的数据(访问和存取器)

    • 维基百科:

数据传输对象(DTO)是在两个进程之间承载数据的对象。数据传输和业务对象或数据访问对象之间的区别在于,DTO除了存储和检索其自身的数据(调制器和访问器)之外没有任何行为。DTO是不应该包含任何需要测试的业务逻辑的简单对象。

    • 博客园dax.net:

表现层于应用层之间是通过DTO来进行交互的,数据传输对象是没有行为的POCO对象,他的目的是为了对领域对象进行数据封装,实现层与层之间的数据传递。简单来说Model面向业务,我们是通过业务来定义Model的。而DTO是面向UI,通过UI的需求来定义的,通过DTO我们实现了表现层与Model层之间的解耦,表现层不引用Model。如果开发过程中我们的模型变了,而界面没变,我们只需改Model而不需要去改动表现层。

看了这些解释,应该还是有点蒙?

先来看看为什么要使用DTO,我总结了三点

    • 隔离领域模型,使用封装(包括数据结构的精简和合并)的DTO实现改动领域模型而不影响UI,保持领域模型的安全,不暴露业务逻辑。
    • 在分布式模式下,相同的数据结构在不同的场景使用相同的数据结构有不同的需求。
    • DTO的存在也为了帮助减少客户端请求而降低服务器压力,提升效率。

种,非常难于管理,当页面所需要的数据与数据库中的数据不一致的情况如果常常出现,那么我们就需要开始着手准备添加对DTO的支持,并且DTO可以设当的冗余设计来减少DTO种类

在系统中添加DTO主要有以下几部分工作需要完成

    • 设计和添加DTO类。
    • 添加从MO到DTO的转化逻辑。
    • 将原本对MO的使用转换为对DTO的使用。(这里可以看出,要尽早的预判是否需要DTO,以免将来麻烦)

关于DTO就了解到这,下面开始回归正题,介绍AutoMapper工具的使用

AutoMapper入门

安装AutoMapper

    • 从包管理器控制台安装

打开程序包管理器控制台,然后输入命令:Install-Package AutoMapper

    • 从包管理器界面安装

在界面中搜索需要安装的程序集,如AutoMapper.dll

安装完成之后添加到程序集引用中即可。

如何使用AutoMapper

首先,您需要使用源类型和目标类型。目标类型的设计可能受其所在层的影响,但只要成员的名称与源类型的成员匹配,AutoMapper就可以发挥最佳效果。如果您有一个名为“FirstName”的源成员,它将自动映射到名称为“FirstName”的目标成员。AutoMapper也支持拼合。

一旦你有了你的类型,你可以使用MapperConfiguration或者静态Mapper实例和CreateMap为这两种类型创建一个映射。MapperConfiguration通常每个AppDomain只需要一个实例,并且应该在启动过程中实例化。

    • 创建映射的两种方式(左侧的类型是源类型,右侧的类型是目标类型):
    • 静态方式:
    • Mapper.Initialize(cfg => cfg.CreateMap<Order, OrderDto>());
    • 如果您使用的是静态Mapper方法,则每个AppDomain只能进行一次配置。这意味着放置配置代码的最佳位置是在应用程序启动时,例如ASP.NET应用程序的Global.asax文件
    • 实例方式
    • var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());

要执行映射又可以使用静态或实例映射器方法:

    • IMapper mapper = config.CreateMapper();
    • IMapper mapper = new Mapper(config);

大多数应用程序可以使用依赖注入来注入创建的IMapper实例。

    • 可以添加配置到配置类中,方便统一管理(AddProfile),然后通过自己写一下泛型返回自己想要的类型转换,这样可以一次性实例化多种类型映射:
    • Mapper.Initialize(cfg => cfg.AddProfile(new MyProfile()));
    • Mapper.Initialize(cfg => cfg.AddProfile<MyProfile>());
    • var config = new MapperConfiguration(fig => fig.AddProfile(new MyProfile()));
    • var config = new MapperConfiguration(fig => fig.AddProfile< MyProfile>());

处理下面几种情况的方式

属性名称相同

扁平化映射

投影(指定字段)

简单类型映射

使用Profile配置

属性名称不同

条件映射:

空值替换NullSubstitute

忽略属性Ignore

目标属性多于源属性,可以进行预设值

类型转换ITypeConverter

using AutoMapper;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace AutoMapperDemo

{

public static class AutoMapperInitialize

{

static AutoMapperInitialize()

{

Mapper.Initialize(fig => fig.AddProfile<MyProfile>());

}

public class User

{

public int Id { set; get; }

public string Name { set; get; }

public int Age { set; get; }

public User(int i)

{

Id = i;

Name = "muphy-" + i;

Age = 15 + i;

}

public User()

{

Id = 1;

Name = "muphy";

Age = 15;

}

public override string ToString()

{

return "[Name:" + Name + ",Age:" + Age + "]";

}

}

public class UserDto

{

public string Name { set; get; }

public int Age { set; get; }

public override string ToString()

{

return "[Name:" + Name + ",Age:" + Age + "]";

}

}

public class Azi : User

{

public string Like { set; get; }

public Azi(int i) : base(i) { Like = "QiaoFeng"; }

public Azi() { }

public override string ToString()

{

return "[Name:" + Name + ",Age:" + Age + "]";

}

}

public class Product

{

public Supplier Supplier { set; get; }

public decimal GetPrice()

{

return 10;

}

public Product()

{

Supplier = new Supplier();

}

}

public class Supplier

{

public string Name { get; set; }

public Supplier()

{

Name = "伟创力";

}

}

public class ProductDto

{

public string SupplierName { set; get; }

public decimal Price { set; get; }

public override string ToString()

{

return "[Price:" + Price + ",SupplierName:" + SupplierName + "]";

}

}

public class Book : Product

{

public DateTime BuyTime { get { return DateTime.Now; } }

}

public class BookDto : ProductDto

{

public DateTime Date { get; set; }

public int Hour { get; set; }

public int Minute { get; set; }

public override string ToString()

{

return "[Price:" + Price + ",SupplierName:" + SupplierName + ",Date:" + Date + "]";

}

}

public class Source

{

public string Name { get { return "muphy"; } }

public int Width { set; get; }

}

public class Destination

{

public string Name { get; set; }

public string like { get; set; }

public override string ToString()

{

return Name + " Like " + like;

}

}

public class MyProfile : Profile

{

public MyProfile()

{

//类型字段系统

CreateMap<User, UserDto>();

//扁平化映射

CreateMap<Product, ProductDto>();

//投影

CreateMap<Book, BookDto>()

.ForMember(desc => desc.Date, opt => opt.MapFrom(src => src.BuyTime.Date))

.ForMember(desc => desc.Hour, opt => opt.MapFrom(src => src.BuyTime.Hour))

.ForMember(desc => desc.Minute, opt => opt.MapFrom(src => src.BuyTime.Minute));

// 条件映射

CreateMap<Azi, UserDto>().ForMember(desc => desc.Age, opt => opt.MapFrom(src => src.Age< 21));

// 可设置默认值

CreateMap<Source, Destination>().ForMember(desc => desc.like, opt => opt.MapFrom(src =>"azi"));

//可忽视多余值

CreateMap< Destination, Source>().ForMember(desc => desc.Width, opt => opt.Ignore());

//空值替换

CreateMap<Source, Destination>().ForMember(desc => desc.Name, opt =>opt.NullSubstitute("azi"));

//其他设置

CreateMap<User, Azi>()

.BeforeMap((src,desc) => src.Age += 50)

.AfterMap((src,desc)=>desc.Age -=  35)// 设置转换前后的行为

.ReverseMap();//设置反向映射

}

}

// 1.简单静态的方式初始化映射 使用Initialize 两个方法:CreateMap AddProfile(稍后)

public static UserDto AutoMapperConfig1()

{

//Mapper.Initialize(cfg => cfg.CreateMap<User, UserDto>());

//Mapper.Initialize(cfg => cfg.AddProfile(new MyProfile()));

//Mapper.Initialize(cfg => cfg.AddProfile<MyProfile>());

UserDto dto = Mapper.Map<UserDto>(new User(1));

return dto;

}

// 2.简单实例的方式初始化方式映射 使用MapperConfiguration  也有两种方式:CreateMapper方法和Mpapper构造函数

public static UserDto AutoMapperConfig2()

{

MapperConfiguration config = new MapperConfiguration(fig => fig.CreateMap<User, UserDto>());

var mapper = config.CreateMapper();

//IMapper mapper = new Mapper(config);

return mapper.Map<UserDto>(new User(2));

}

// 3.使用继承Profile的配置属性方式映射 AddProfile方法

public static UserDto AutoMapperConfig3()

{

MapperConfiguration config = new MapperConfiguration(fig => fig.AddProfile<MyProfile>());

IMapper mapper = new Mapper(config);

return mapper.Map<UserDto>(new User(3));

}

// 4.使用继承Profile的配置属性 + 泛型方式映射 效果会更好

public static T AutoMapperConfig4<K, T>(K k)

{

return Mapper.Map<T>(k);

}

// 5.扁平化映射

public static ProductDto AutoMapperConfig5()

{

MapperConfiguration config = new MapperConfiguration(fig => fig.AddProfile<MyProfile>());

var mapper = config.CreateMapper();

return mapper.Map<ProductDto>(new Product());

}

}

}

AutoMapper入门使用的更多相关文章

  1. AutoMapper之如何开始,适合入门和演示

    原来想应该介绍下背景说明下好处什么的,仔细想都是废话 ,直接上代码吧. 首先有两个类,一个是和数据库对应的实体 Student,一个是和页面展示相关的页面模型 StudentModel. /// &l ...

  2. 00.AutoMapper 之入门指南(Getting Started Guide)

    转载(https://www.jianshu.com/p/29ee5a94c1d9) 入门指南(Getting Started Guide) AutoMapper 是什么? AutoMapper 是一 ...

  3. Asp.net Core 2.2关于AutoMapper更初级的入门教程

    今天刚看到老张的哲学博客关于AutoMapper的教程,从壹开始前后端分离[ .NET Core2.0 +Vue2.0 ]框架之十三 || DTOs 对象映射使用,项目部署Windows+Linux完 ...

  4. ABP(现代ASP.NET样板开发框架)系列之2、ABP入门教程

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

  5. AutoMapper之ABP项目中的使用介绍

    最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMapper只要用来数据转换,在园里已经有很多 ...

  6. ABP入门系列(6)——展现层实现增删改查

    这一章节将通过完善Controller.View.ViewModel,来实现展现层的增删改查.最终实现效果如下图: 一.定义Controller ABP对ASP.NET MVC Controllers ...

  7. ABP入门系列(5)——创建应用服务

    一.解释下应用服务层 应用服务用于将领域(业务)逻辑暴露给展现层.展现层通过传入DTO(数据传输对象)参数来调用应用服务,而应用服务通过领域对象来执行相应的业务逻辑并且将DTO返回给展现层.因此,展现 ...

  8. 基于DDD的现代ASP.NET开发框架--ABP系列之2、ABP入门教程

    基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boi ...

  9. ABP项目中的使用AutoMapper

    AutoMapper之ABP项目中的使用 最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMa ...

随机推荐

  1. 从.Net到Java学习第六篇——SpringBoot+mongodb&Thymeleaf&模型验证

    SpringBoot系列目录 SpringBoot整合mongodb MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.如果你没用过Mong ...

  2. angular应用容器化部署

    angular 应用容器化部署 Intro 我自己有做一个个人主页,虽然效果不怎么样(不懂设计的典型程序猿...),但是记录了我对于前端框架及工具的一些实践, 从开始只有一个 angularjs 制作 ...

  3. centos7 安装java运行环境

    1.检测是否存在相关历史版本 shell:java-version 1.1.存在相关OpenJDK和其他版本SDK则需要删除,如图. 查看详细信息,命令窗口输入,shell:rpm -qa | gre ...

  4. Oracle 查询权限视图

    在Oracle中有很多用于查权限的视图,但很多人在需要查权限时会很困惑,不知道该用哪个视图去查,这里我列出几个常见的用于查权限的视图及其用法: 1DBA_ROLE_PRIVS 该视图主要有以下2个作用 ...

  5. c/c++ llinux epoll系列4 利用epoll_wait实现非阻塞的connect

    llinux epoll系列4 利用epoll_wait实现非阻塞的connect connect函数是阻塞的,而且不能设置connect函数的timeout时间,所以一旦阻塞太长时间,影响用户的体验 ...

  6. Tmux 入门

    什么是 Tmux Tmux 官方 Wiki 简单来说,Tmux 是一个能够让你一个窗口当多个窗口使用的终端模拟器.并且你还可以将它放到后台,等到想使用的时候再使用. 为什么要用 Tmux 在服务器上调 ...

  7. 我的第一个python web开发框架(22)——一个安全小事故

    在周末的一个早上,小白还在做着美梦,就收到了小美的连环追魂call,电话一直响个不停. 小白打着哈欠拿起电话:早上好美女. 小美:出事了出事了,我们公司网站一早访问是一片空白,什么内容都没有了,你赶急 ...

  8. Redis数据过期策略详解

    http://www.cnblogs.com/xuliangxing/p/7151812.html 本文对Redis的过期机制简单的讲解一下 讲解之前我们先抛出一个问题,我们知道很多时候服务器经常会用 ...

  9. solr 7.7 搭建和搜索

    最近做了个solr搜索的demo, 用的是solr7.7,之前网上好多文章搭建solr都是5.5+tomcat.. 自己摆弄了下,发现solr7.7和5.5 的部分文件夹有些改动,没有深究原理也就没有 ...

  10. .net core iis配置

    微软官方教程: https://docs.microsoft.com/en-us/aspnet/core/publishing/iis?tabs=aspnetcore2x 在vs中创建.net cor ...