简介

很多时候我们使用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
}

AutoMapper6扩展的更多相关文章

  1. Asp.net Boilerplate之AbpSession扩展

    当前Abp版本1.2,项目类型为MVC5. 以属性的形式扩展AbpSession,并在"记住我"后,下次自动登录也能获取到扩展属性的值,版权归"角落的白板报"所 ...

  2. 恢复SQL Server被误删除的数据(再扩展)

    恢复SQL Server被误删除的数据(再扩展) 大家对本人之前的文章<恢复SQL Server被误删除的数据> 反应非常热烈,但是文章里的存储过程不能实现对备份出来的日志备份里所删数据的 ...

  3. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

  4. .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类

    .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类 0x00 为什么要引入扩展方法 有的中间件功能比较简单,有的则比较复杂,并且依赖其它组件.除 ...

  5. 采用EntityFramework.Extended 对EF进行扩展(Entity Framework 延伸系列2)

    前言 Entity Framework 延伸系列目录 今天我们来讲讲EntityFramework.Extended 首先科普一下这个EntityFramework.Extended是什么,如下: 这 ...

  6. Dapper扩展之~~~Dapper.Contrib

    平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html#skill 上一篇文章:Dapper逆天入门~强类型,动态类型 ...

  7. ExtJS 4.2 Date组件扩展:添加清除按钮

    ExtJS中除了提供丰富的组件外,我们还可以扩展他的组件. 在这里,我们将在Date日期组件上添加一个[清除]按钮,用于此组件已选中值的清除. 目录 1. Date组件介绍 2. 主要代码说明 3. ...

  8. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  9. Hawk 6. 编译和扩展开发

    Hawk是开源项目,因此任何人都可以为其贡献代码.作者也非常欢迎使用者能够扩展出更有用的插件. 编译 编译需要Visual Stuido,版本建议使用2015, 2010及以上没有经过测试,但应该可以 ...

随机推荐

  1. Ubuntu 安装ftp

    Ubuntu 用vsftpd 配置FTP服务器 网上的文章好难懂啊..只想要简单粗暴,弄好能用就行啊,复杂的以后研究不行吗...折腾好久,其实弄出来能用不就这么点内容吗... 本文在Ubuntu Se ...

  2. spring boot快速入门 5: 事务管理

    事务管理: 新增两名女生: 第一步:创建 GirlRespository package com.payease.service; import com.payease.entity.Girl; im ...

  3. PHP 对字符串 进行填充

    1.str_pad — 使用另一个字符串填充字符串为指定长度 . 我觉得str_pad可以满足普通的数字,字符串的简单填充. string str_pad ( string $input , int ...

  4. redis 数据库迁移

    老大让把 一台机器上 redis 中所有的数据,迁移到另一台机器上 查了一下可以拷贝 rdb 文件, 此方法只适用于迁移到一个新的库, 迁移到正在使用的库就不行了, 而且 rdb 里面是所有的 db, ...

  5. Linux常用命令之tr

    tr NAME tr - translate or delete characters 可以对来自标准输入的字符进行替换.压缩和删除.它可以将一组字符变成另一组字符,经常用来编写优美的单行命令,作用很 ...

  6. FocusBI: 《DW/BI项目管理》之数据库表结构 (原创)

    关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. <商业智能教程>pdf下载地址 链接:https://pan.baidu.com/ ...

  7. 得到DataGrid列的值

    <mx:DataGridColumn headerText="状态" dataField="D30120_ZH" width="80" ...

  8. Mongo db 与mysql 语法比较

    mongodb与mysql命令对比 传统的关系数据库一般由数据库(database).表(table).记录(record)三个层次概念组成,MongoDB是由数据库(database).集合(col ...

  9. vue之生命周期的一点总结

    vue的生命周期的过程提供了我们执行自定义逻辑的机会,好好理解它的生命周期,对我们很有帮助. 一.vue实例的生命周期(vue2.0) 二.生命周期描述:(参考截图) 三.例子 window.vm = ...

  10. 深入理解 flex 布局以及计算_Flexbox, Layout

    起因 对于Flex布局,阅读了 大漠老师和其他老师写的文章后,我还是不太理解Flexbox是如何弹性的计算子级项目的大小以及一些其他细节.在大漠老师的帮助下,我去查阅Flexbox 的 W3C 规范文 ...