AutoMapper 6.x 扩展
简介
很多时候我们使用AutoMapper的时候,都需要进行一个配置才可以使用Mapper.Map<Source,Target>(entity);。如果不进行配置则会报错。
如果实体过多,有时候会忘记是否有配置,只有运行的时候才会发现这个BUG。
源代码地址
源代码
该扩展基于AutoMapper 6.x版本,因此需要从Nuget下载相应的包。
该扩展对于Object以及List<T>进行了兼容支持,因此MapTo<TSource,TDestination>()可以直接映射实体与泛型列表。
/// <summary>
/// AutoMapper 对象映射扩展
/// </summary>
public static partial class Extensions
{
/// <summary>
/// 同步锁
/// </summary>
private static readonly object Sync=new object();
#region MapTo(将源对象映射到目标对象)
/// <summary>
/// 将源对象映射到目标对象
/// </summary>
/// <typeparam name="TSource">源类型</typeparam>
/// <typeparam name="TDestination">目标类型</typeparam>
/// <param name="source">源对象</param>
/// <param name="destination">目标对象</param>
/// <returns></returns>
public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
{
return MapTo<TDestination>(source, destination);
}
/// <summary>
/// 将源对象映射到目标对象
/// </summary>
/// <typeparam name="TDestination">目标类型</typeparam>
/// <param name="source">源对象</param>
/// <returns></returns>
public static TDestination MapTo<TDestination>(this object source) where TDestination : new()
{
return MapTo(source, new TDestination());
}
/// <summary>
/// 将源对象映射到目标对象
/// </summary>
/// <typeparam name="TDestination">目标类型</typeparam>
/// <param name="source">源对象</param>
/// <param name="destination">目标对象</param>
/// <returns></returns>
private static TDestination MapTo<TDestination>(object source, TDestination destination)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
var sourceType = GetType(source);
var destinationType = GetType(destination);
var map = GetMap(sourceType, destinationType);
if (map != null)
{
return Mapper.Map(source, destination);
}
lock (Sync)
{
map = GetMap(sourceType, destinationType);
if (map != null)
{
return Mapper.Map(source, destination);
}
InitMaps(sourceType, destinationType);
}
return Mapper.Map(source, destination);
}
/// <summary>
/// 获取映射配置
/// </summary>
/// <param name="sourceType">源类型</param>
/// <param name="destinationType">目标类型</param>
/// <returns></returns>
private static TypeMap GetMap(Type sourceType, Type destinationType)
{
try
{
return Mapper.Configuration.FindTypeMapFor(sourceType, destinationType);
}
catch (InvalidOperationException)
{
lock (Sync)
{
try
{
return Mapper.Configuration.FindTypeMapFor(sourceType, destinationType);
}
catch (InvalidOperationException)
{
InitMaps(sourceType, destinationType);
}
return Mapper.Configuration.FindTypeMapFor(sourceType, destinationType);
}
}
}
/// <summary>
/// 获取类型
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
private static Type GetType(object obj)
{
var type = obj.GetType();
if (obj is System.Collections.IEnumerable == false)
{
return type;
}
if (type.IsArray)
{
return type.GetElementType();
}
var genericArgumentsTypes = type.GetTypeInfo().GetGenericArguments();
if (genericArgumentsTypes == null || genericArgumentsTypes.Length == 0)
{
throw new ArgumentException("泛型类型参数不能为空");
}
return genericArgumentsTypes[0];
}
/// <summary>
/// 初始化映射配置
/// </summary>
/// <param name="sourceType">源类型</param>
/// <param name="destinationType">目标类型</param>
private static void InitMaps(Type sourceType, Type destinationType)
{
try
{
var maps = Mapper.Configuration.GetAllTypeMaps();
Mapper.Initialize(config =>
{
ClearConfig();
foreach (var item in maps)
{
config.CreateMap(item.SourceType, item.DestinationType);
}
config.CreateMap(sourceType, destinationType);
});
}
catch (InvalidOperationException)
{
Mapper.Initialize(config =>
{
config.CreateMap(sourceType, destinationType);
});
}
}
/// <summary>
/// 清空配置
/// </summary>
private static void ClearConfig()
{
var typeMapper = typeof(Mapper).GetTypeInfo();
var configuration = typeMapper.GetDeclaredField("_configuration");
configuration.SetValue(null, null, BindingFlags.Static, null, CultureInfo.CurrentCulture);
}
#endregion
#region MapToList(将源集合映射到目标列表)
/// <summary>
/// 将源集合映射到目标列表
/// </summary>
/// <typeparam name="TDestination">目标元素类型,范例:Sample,不用加List</typeparam>
/// <param name="source">源集合</param>
/// <returns></returns>
public static List<TDestination> MapToList<TDestination>(this System.Collections.IEnumerable source)
{
return MapTo<List<TDestination>>(source);
}
#endregion
}
AutoMapper 6.x 扩展的更多相关文章
- AutoMapper 6.x 扩展方法
简介 很多时候我们使用AutoMapper的时候,都需要进行一个配置才可以使用Mapper.Map<Source,Target>(entity);.如果不进行配置则会报错. 如果实体过多, ...
- C# AutoMapper的简单扩展
AutoMapper可以很方便的将一个实体的属性值转化给另一个对象.这个功能在我们日常的编码中经常会遇到.我将AutoMapper的一些基本映射功能做成扩展方法,在编码中更方便使用. using Sy ...
- 【AutoMapper官方文档】DTO与Domin Model相互转换(下)
写在前面 AutoMapper目录: [AutoMapper官方文档]DTO与Domin Model相互转换(上) [AutoMapper官方文档]DTO与Domin Model相互转换(中) [Au ...
- DTO学习系列之AutoMapper(四)
本篇目录: Mapping Inheritance-映射继承 Queryable Extensions (LINQ)-扩展查询表达式 Configuration-配置 Conditional Mapp ...
- AutoMapper6扩展
简介 很多时候我们使用AutoMapper的时候,都需要进行一个配置才可以使用Mapper.Map<Source,Target>(entity);.如果不进行配置则会报错. 如果实体过多, ...
- netcore 2.2 封装 AutoMapper
在上篇中我们通过创建一个类并继承autoMapper的Profile类 public class Mappings : Profile { public Mappings() { CreateMap& ...
- (28)ASP.NET Core AutoMapper组件
1.什么是AutoMapper? AutoMapper是一个对象-对象映射器.对象-对象映射通过将一种类型的输入对象转换为另一种类型的输出对象来工作.使AutoMapper变得有趣的是,它提供了一些有 ...
- nopCommerce 3.9 大波浪系列 之 引擎 NopEngine
本章涉及到的内容如下 1.EngineContext初始化IEngine实例 2.Autofac依赖注入初始化 3.AutoMapper框架初始化 4.启动任务初始化 一.EngineContext初 ...
- Asp.net 面向接口可扩展框架之使用“类型转化基础服务”测试四种Mapper(AutoMapper、EmitMapper、NLiteMapper及TinyMapper)
Asp.net 面向接口可扩展框架的“类型转化基础服务”是我认为除了“核心容器”之外最为重要的组成部分 但是前面博文一出,争议很多,为此我再写一篇类型转化基础服务和各种Mapper结合的例子,顺便对各 ...
随机推荐
- B计划
简介:从一个初学者的角度来讲,要从六个方面来对计算机来做一个大约的了解: 计算机的组成: 电脑配置: 操作系统: CDEF盘: 正确的开关机(主要是关机): 常用软件: 1. 电脑由哪几部分组成? ...
- 基于HTML5 Canvas实现用户交互
很多人都有这样的疑问,基于HTML5 Canvas实现的元素怎么和用户进行交互?在这里我们用到HT for Web(http://www.hightopo.com/guide/guide/core/b ...
- SPFA求单源最短路径
序 求最短路径的算法有很多,各有优劣. 比如Dijkstra(及其堆(STL-priority_queue)优化),但是无法处理负环的情况: 比如O(n^3)的Floyd算法:比如Bellman-Fo ...
- Github+Hexo,搭建专属网站
前言 记得从大二开始,就一直想搭个专属网站,当时使劲抠页面[前端页面是从QQ空间抠的,现在想抠估计没这么容易了],写代码,忙活半天才把程序弄好. 可惜最终项目还是没上线,因为当时有两问题绕不开 需要购 ...
- AbstractHandlerMapping解读
一.AbstractHandlerMapping简介 AbstractHandlerMapping是HandlerMapping的抽象实现,所有的HandlerMapping都继承自AbstractH ...
- springcloud(十):服务网关zuul
前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个 ...
- 连接Oracle数据库的时候报了“Got minus one from a read call”
(转) 出现这种问题基本上就以下几种原因,可以查一下系统日志看看:1:数据库连接满了,扩大数据库连接池2:所登录的机子IP不在sqlnet.ora内,加入后重启listerner即可3:数据库负载均衡 ...
- 网络编程应用:基于UDP协议【实现文件下载】--练习
要求: 基于UDP协议实现文件下载 发送方–请求–接收方发送文件–发送方接收文件 代码: 发送方: package Homework1; import java.io.File; import jav ...
- canvas——随机生成迷宫
先上图. 效果 代码 随机生成迷宫要求任意两点都能够找到相同的路径,也就是说,迷宫是一个连通图.随机生成迷宫可以使用普里姆算法.广度优先算法.深度优先算法等实现.这里将使用普里姆算法通过生成最小数的方 ...
- 【Web开发】Mean web开发 01-Express实现MVC模式开发
简介 Mean是JavaScript的全栈开发框架.更多介绍 用Express实现MVC模式开发是Mean Web全栈开发中的一部分. Express 是一个基于 Node.js 平台的极简.灵活的 ...