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结合的例子,顺便对各 ...
随机推荐
- Docker4Windows -- 从外部(非本机host)访问 由docker container运行的程序
背景 当我们在windows 上面运行docker container的时候,我们需要借助于模拟器(例如,Virtual box/Hyper V),她的目的主要是在我们的windows系统上面模拟出一 ...
- 基于java的正则表达式
正则表达式概念 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描 ...
- mysql数据库小常识
什么是数据库? 计算机处理和存储的一切信息都是数据. 计算机系统中一种用于存储数据的程序. 一种:计算机系统中有很多种能够存取数据的程序. 他们各有特长和长处,有自己的适用范围. 存取:能够保存数据避 ...
- 图的M着色问题
问题描述: 给定无向连通图 G 和 m 种不同的颜色.用这些颜色为图 G 和各顶点着色,每个顶点着一种颜色.是否有一种着色法使得图 G 中每条边的两个顶点着不同的颜色.这个问题是图的 m 可着色判定问 ...
- File 常用方法
1.判断当前文件是否封装的文件夹目录 //返回true--是,false--不是 File file =new File("C:\\Users\\mac\\Desktop\\复习.txt&q ...
- 利刃 MVVMLight
已经很久没有写系列文章了,上一次是2012年写的HTLM5系列,想想我们应该是较早一批使用HTML5做项目的人. 相比我当时动不动100+的粉丝增长和两天3000+的阅读量,MVVM Light只能算 ...
- 目前微信 微博 新浪 豆瓣等所有分享的js插件
原理 功能 集成微信.微博.开心.豆瓣.人人.qq微博.搜狐.qq空间等分享 即时分享: 默认加载插件,即启动全部分享 定制分享:通过参数配置.静态数据配置 由你决定何时分享,如何分享 扩展: 通过数 ...
- Windows server 2008 r2 开启Aero
1.右键“计算机”----“管理”----“添加功能”,选上“桌面体验”,一般来说要把服务器系统做成工作 站的话,最好再选上“优质WINDOWS音频视频体验”,如果有无线网卡再选上“无线LAN服务”, ...
- (转)Javascript的DOM操作 - 性能优化
转载:https://my.oschina.net/blogshi/blog/198910 摘要: 想稍微系统的说说对于DOM的操作,把Javascript和jQuery常用操作DOM的内容归纳成思维 ...
- 对于JSONObject,我只是临时抱佛脚
说起JSON,大家就谈不上陌生了,因为对于数据传输语言,各位只认json,即使有XML语言,但是各位很少用吧.我也是,但是之前用过的json转换工具各种各样,我记忆中有过GSON(google).fa ...