(28)ASP.NET Core AutoMapper组件
1.什么是AutoMapper?
AutoMapper是一个对象-对象映射器。对象-对象映射通过将一种类型的输入对象转换为另一种类型的输出对象来工作。使AutoMapper变得有趣的是,它提供了一些有趣的约定,免去用户不需要了解如何将类型A映射为类型B。只要类型B遵循AutoMapper既定的约定,就需要几乎零配置来映射两个类型。映射代码虽然比较无聊,但是AutoMapper为我们提供简单的类型配置以及简单的映射测试,而映射可以在应用程序中的许多地方发生,但主要发生在层之间的边界中,比如,UI /域层之间或服务/域层之间。一层的关注点通常与另一层的关注点冲突,因此对象-对象映射导致分离的模型,其中每一层的关注点仅会影响该层中的类型。
2.如何在Core上面使用AutoMapper组件?
先在Startup.ConfigureServices注入AutoMapper组件服务,然后在Startup.Configure上获取AutoMapper服务配置扩展类创建对象-对象映射关系,为了好统一管理代码,可以新建一个AutoMapperExtension静态类,把以下代码封装一下:
public static class AutoMapperExtension
{
/// <summary>
/// 新增自动映射服务
/// </summary>
/// <param name="service"></param>
/// <returns></returns>
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
#region 方案一
//注册AutoMapper配置扩展类服务
services.TryAddSingleton<MapperConfigurationExpression>();
//注册AutoMapper配置扩展类到AutoMapper配置服务去
services.TryAddSingleton(serviceProvider =>
{
var mapperConfigurationExpression = serviceProvider.GetRequiredService<MapperConfigurationExpression>();
var mapperConfiguration = new MapperConfiguration(mapperConfigurationExpression);
mapperConfiguration.AssertConfigurationIsValid();
return mapperConfiguration;
});
//注入IMapper接口DI服务
services.TryAddSingleton(serviceProvider =>
{
var mapperConfiguration = serviceProvider.GetRequiredService<MapperConfiguration>();
return mapperConfiguration.CreateMapper();
});
return services;
#endregion
} /// <summary>
/// 使用自动映射配置扩展类
/// </summary>
/// <param name="applicationBuilder"></param>
/// <returns></returns>
public static IMapperConfigurationExpression UseAutoMapper(this IApplicationBuilder applicationBuilder)
{
//获取已注册服务AutoMapper配置扩展类
return applicationBuilder.ApplicationServices.GetRequiredService<MapperConfigurationExpression>();
}
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
......
//添加自动映射组件DI服务
services.AddAutoMapper();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
......
//注册组件之后,创建映射对象
var expression = app.UseAutoMapper();
expression.CreateMap<Customer, CustomerDto>();
expression.CreateMap<Address, AddressDto>();
}
因为IMapper接口已经在ConfigureServices方法注入DI服务了,所以无需再重新注入,只需要直接使用IMapper调用其方法就可以:
public class BlogsController : Controller
{
private IMapper _iMapper { get; }
public BlogsController(IMapper iMapper)
{
_iMapper = iMapper;
}
// GET: Blogs
public async Task<IActionResult> Index()
{
//对象-对象数据传输
var dto = _iMapper.Map<CustomerDto>(CustomerInitialize());
......
}
//手动赋值客户对象数据
private Customer CustomerInitialize()
{
var _customer = new Customer()
{
Id = ,
Name = "Eduardo Najera",
Credit = 234.7m,
Address = new Address() { City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad." },
HomeAddress = new Address() { City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad." },
WorkAddresses = new List<Address>()
{
new Address() {City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad."},
new Address() {City = "izmir", Country = "turkey", Id = , Street = "konak"}
},
Addresses = new List<Address>()
{
new Address() {City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad."},
new Address() {City = "izmir", Country = "turkey", Id = , Street = "konak"}
}.ToArray()
};
return _customer;
}
}
运行效果:

3.如果更加灵活使用AutoMapper组件?
相信在第二章节时候,相信大家都会发现一个问题,如果生产场景业务越来越庞大,需创建对应业务对象也会越来越多,如果面对这样的业务场景难道要在Configure方法里面创建越来越多的映射关系吗?例:
var expression = app.UseAutoMapper();
expression.CreateMap<A, ADto>();
expression.CreateMap<B, BDto>();
expression.CreateMap<C, CDto>();
expression.CreateMap<D, DDto>();
......
很显然这样子是不可行的,这样会导致后续代码越来越多,难以维护。那么现在让我们来解决这个问题。首先新建一个自动注入属性的AutoInjectAttribute密封类,具体代码如下:
public sealed class AutoInjectAttribute : Attribute
{
public Type SourceType { get; }
public Type TargetType { get; }
public AutoInjectAttribute(Type sourceType, Type targetType)
{
SourceType = sourceType;
TargetType = targetType;
}
}
新增这个AutoInjectAttribute密封类,目的是声明每个DTO对象(数据传输对象)与对应数据源对象是传输关系,方便在Configure里面自动注册创建映射关系,例:
//声明源对象,目标对象
[AutoInject(sourceType: typeof(Customer),targetType:typeof(CustomerDto))]
public class CustomerDto
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public AddressDto HomeAddress { get; set; }
public AddressDto[] Addresses { get; set; }
public List<AddressDto> WorkAddresses { get; set; }
public string AddressCity { get; set; }
}
然后创建一个自动注入AutoInjectFactory工厂类,检测运行中的程序集是否有AutoInjectAttribute属性声明,如果有则插入一个类型数据集中返回,目的是把所有声明需要映射DTO对象跟数据源对象自动创建映射关系:
public class AutoInjectFactory
{
public List<(Type, Type)> AddAssemblys
{
get
{
var assemblys =new List<Assembly>() { Assembly.GetExecutingAssembly() };
List<(Type, Type)> ConvertList = new List<(Type, Type)>();
foreach (var assembly in assemblys)
{
var atributes = assembly.GetTypes()
.Where(_type => _type.GetCustomAttribute<AutoInjectAttribute>() != null)
.Select(_type => _type.GetCustomAttribute<AutoInjectAttribute>());
foreach (var atribute in atributes)
{
ConvertList.Add((atribute.SourceType, atribute.TargetType));
}
}
return ConvertList;
}
}
}
在第2小节AutoMapperExtension静态类的AddAutoMapper方法内修改如下代码:
#region 方案二
//注入AutoMapper配置扩展类服务
services.TryAddSingleton<MapperConfigurationExpression>();
//注入自动注入工厂类服务
services.TryAddSingleton<AutoInjectFactory>();
//注入AutoMapper配置扩展类到AutoMapper配置服务去
services.TryAddSingleton(serviceProvider =>
{
var mapperConfigurationExpression = serviceProvider.GetRequiredService<MapperConfigurationExpression>();
//通过自动注入工厂类获取声明数据源对象与DTO对象自动创建映射关系
var factory = serviceProvider.GetRequiredService<AutoInjectFactory>();
foreach (var (sourceType, targetType) in factory.AddAssemblys)
{
mapperConfigurationExpression.CreateMap(sourceType, targetType);
}
var mapperConfiguration = new MapperConfiguration(mapperConfigurationExpression);
mapperConfiguration.AssertConfigurationIsValid();
return mapperConfiguration;
});
//注入IMapper接口DI服务
services.TryAddSingleton(serviceProvider =>
{
var mapperConfiguration = serviceProvider.GetRequiredService<MapperConfiguration>();
return mapperConfiguration.CreateMapper();
});
return services;
#endregion
再新增一个使用自动注入工厂类服务静态方法:
/// <summary>
/// 使用自动注入工厂类
/// </summary>
/// <param name="applicationBuilder"></param>
public static void UseAutoInject(this IApplicationBuilder applicationBuilder)
{
applicationBuilder.ApplicationServices.GetRequiredService<AutoInjectFactory>();
}
然后在Startup.ConfigureServices注入AutoMapper组件服务,然后在Startup.Configure上调用UseAutoInject静态方法,具体代码如下:
app.UseAutoInject();
运行效果:
从运行结果来看依然是这个酸爽!
参考文献:
AutoMapper
(28)ASP.NET Core AutoMapper组件的更多相关文章
- 笔记: ASP.NET Core视图组件
视图组件 asp.net core mvc 提供了部分视图的新替代品:视图组件. 视图组件与分布视图的主要区别在于视图组件与控制器不相关.可使用在独立于单个控制器的场景,如:菜单导航.侧边栏.分页栏等 ...
- Blazor入门:ASP.NET Core Razor 组件
目录 关于组件 组件类 静态资产 路由与路由参数 组件参数 请勿创建会写入其自己的组参数属性的组件 子内容 属性展开 任意参数 捕获对组件的引用 在外部调用组件方法以更新状态 使用 @ 键控制是否保留 ...
- asp.net core 视图组件(转)
介绍视图组件 视图组件是 ASP.NET Core MVC 中的新特性,与局部视图相似,但是它们更加的强大.视图组件不使用模型绑定,只取决于调用它时所提供的数据.视图组件有以下特点: 渲染一个块,而不 ...
- asp.net core日志组件
日志介绍 Logging的使用 1. appsettings.json中Logging的介绍 Logging的配置信息是保存在appsettings.json配置文件中的.因为之前介绍配置文件的时候我 ...
- asp.net core 视图组件化
视图组件可以通过partial view或viewcomponent实现 partialview https://docs.microsoft.com/zh-cn/aspnet/core/mvc/vi ...
- asp.net core视图组件(ViewComponent)简单使用
一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. 定义一个视图组件,如控制器一样,必须是公开,非嵌套,非抽象的类.一般,视图组件名称为类名去掉&qu ...
- Asp.Net core 视图组件ViewComponent
视图组件 ViewComponent 最近用了一下视图组件,还挺方便的,如果遇到公共的部分,可以抽出来,写成视图组件,方便调用 先上图看一下效果:比如首页的4个画红框的地方是4个模块,有些地方可能要重 ...
- [转]asp.net core视图组件(ViewComponent)简单使用
本文转自:http://www.cnblogs.com/dralee/p/6170496.html 一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. ...
- ASP NET Core ---Automapper
官方文档:http://docs.automapper.org/en/stable/index.html 一.安装和配置: 二.使用: 1.建立 Profile文件: public class Map ...
随机推荐
- 88)PHP,PDOStatement对象
PDOStatement类,称之为PDO语句对象,SQL执行完(处理完)产生的结果对象. fetchColumn(index=) 允许传递参数,表示获得第一条记录的第几个字段的值. 相当于 getOn ...
- NI Vision 介绍
NI Vision主要包括三种主要软件包: 主程序包(Vision Acquisition Software), 视觉开发模块(Vision Development Module), 以及用于自动检测 ...
- Django连接SQL Server,安装相关扩展包及相关配置
1.python下载 https://www.python.org/downloads/windows/ 2.根据当前windows和python的版本,下载pymssql相应的exe安装文件. ht ...
- Java 线程总结(十四)
1.在异步任务进程中,一种常见的场景是,主线程提交多个异步任务,然后希望有任务完成就处理结果,并且按任务完成顺序逐个处理,对于这种场景,Java 并发包提供了一个方便的方法,使用 Completion ...
- Mysql主从同步原理简介
1.定义:当master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库. 2.好处: 1)水平扩展数据库的负载能力. 2)容错,高可用.Failover(失败切换)/High Av ...
- zabbix的MariaDB数据库改变存储位置
#创建 mkdir /公司缩写/mysql #停止数据库服务 systemctl status mariadb.service systemctl stop mariadb.service # ...
- python3下scrapy爬虫(第二卷:初步抓取网页内容之直接抓取网页)
上一卷中介绍了安装过程,现在我们开始使用这个神奇的框架 跟很多博主一样我也先选择一个非常好爬取的网站作为最初案例,那么我先用屌丝必备网站http://www.shaimn.com/xinggan/作为 ...
- 史上最全Java面试题全集
2013年年底的时候,我看到了网上流传的一个叫做<Java面试题大全>的东西,认真的阅读了以后发现里面的很多题目是重复且没有价值的题目,还有不少的参考答案也是错误的,于是我花了半个月时间对 ...
- SpringBoot多数据源中的分布式事务
虽然现在微服务越来越流行,我们的系统随之也拆分出来好多的模块功能.这样做的目的其实就是为了弥补单体架构中存在的不足.随着微服务的拆分,肯定设计到分库分表,但这之中肯定设计到分布式事务.最典型的例子就是 ...
- <HAOI2008>硬币购物
和神奇dp的战斗 还有容斥原理 终于get到了 #include<cstdio> #include<cstring> #include<iostream> #inc ...