using AutoMapper;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Common
{
public static class MapperHelper
{
///
/// 同步锁
///
private static readonly object Sync = new object();
///
/// 将源对象映射到目标对象
///
/// 源类型
/// 目标类型
/// 源对象
/// 目标对象
public static TDestination MapTo(this TSource source, TDestination destination)
{
return MapTo(source, destination);
}
///
/// 将源对象映射到目标对象
///
/// 目标类型
/// 源对象
public static TDestination MapTo(this object source) where TDestination : new()
{
return MapTo(source, new TDestination());
}
///
/// 将源对象映射到目标对象
///
private static TDestination MapTo(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);
}
///
/// 获取类型
///
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];
}
///
/// 获取映射配置
///
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);
}
}
}
///
/// 初始化映射配置
///
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);
});
}
}
///
/// 清空配置
///
private static void ClearConfig()
{
var typeMapper = typeof(Mapper).GetTypeInfo();
var configuration = typeMapper.GetDeclaredField("_configuration");
configuration.SetValue(null, null, BindingFlags.Static, null, CultureInfo.CurrentCulture);
}
///
/// 将源集合映射到目标集合
///
/// 目标元素类型,范例:Sample,不要加List
/// 源集合
public static List MapToList(this System.Collections.IEnumerable source)
{
return MapTo>(source);
}
}
}