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. 如何获取Debug Android Hash Key

    在接入FaceBook第三方登录的时候,需要获取Android Hash Key. Android Hash Key即密钥散列有两种,一种是开发秘钥散列,一种是发布秘钥散列.这里主要介绍如何获取开发秘 ...

  2. 如何获得MIUI10系统的root超级权限

    MIUI10系统有没有办法拥有root超级权限?做开发的人都清楚,android手机有root超级权限,如果手机拥有root相关权限,能够实现更强的功能,举个栗子做开发的人企业的营销部门,使用某些营销 ...

  3. Django2.0 正则表示匹配的简单例子

    在Django中,使用正则表达式,匹配Url 默认情况下,url固定格式如下: urlpatterns = [ path('admin/', admin.site.urls), ] 如果需要使用正则表 ...

  4. PJProject(2.6) 工程介绍

    pjlib pjlib\build\pjlib.vcproj pjlib_test pjlib\build\pjlib_test.vcproj pjsip_core pjsip\build\pjsip ...

  5. Spring MVC 响应视图(六)

    完整的项目案例: springmvc.zip 目录 实例 除了依赖spring-webmvc还需要依赖jackson-databind(用于转换json数据格式) <dependency> ...

  6. 执行C#动态代码

    执行C#动态代码 using System; using System.Data; using System.Configuration; using System.Text; using Syste ...

  7. 【iOS开发】Alamofire框架的使用二 高级用法

    Alamofire是在URLSession和URL加载系统的基础上写的.所以,为了更好地学习这个框架,建议先熟悉下列几个底层网络协议栈: URL Loading System Programming ...

  8. Windows10系统无法更新

    方法一: 1.先检查一下windows update服务是否开启,并禁用杀毒软件: 2.如果此服务已经启动,先尝试更换一下网络环境重新更新: 3.如果更换网络环境后依然无法更新,就删除windows ...

  9. iOS Password AutoFill开发指南

    转载请标明来源:https://www.cnblogs.com/zhanggui/p/9431950.html 引言 在<iPhone User Guide for iOS 11.4>这本 ...

  10. 超哥笔记 --nginx入门(6)

    一 NGINX 1 nignx是什么 nginx是一个开源的支持高性能,高并发的web服务和代理服务软件. nginx比他大哥apache性能改进许多,nginx占用的系统资源更少,支持高并发连接,有 ...