1 准备工作
通过Nuget引用:“AutoMapper”或“AutoMapper.Extensions.Microsoft.DependencyInjection”都可以,至于引用那个由两者的最新版本决定。
2 Core.Infrastructure.AutoMapper.IorderedMapperProfile
namespace Core.Infrastructure.AutoMapper
{
/// <summary>
/// 【顺序映射配置--接口】
/// <remarks>
/// 摘要:
/// 继承于该接口的具体实现类中的成员方法例化当前类中的两个静态属性成员:
/// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
/// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
/// </remarks>
/// </summary>
public interface IOrderedMapperProfile
{
/// <summary>
/// 【顺序】
/// <remarks>
/// 摘要:
/// 继承于当前接口的所有的具体实现类,被实例化时顺序;即在通过该接口批量实例化所有的具体实现类时,将按照指定具体实现类该属性成员值的排序顺序,依次的获取这些具体实现类的实例。
/// </remarks>
/// </summary>
int Order { get; }
}
}
3 Core.Infrastructure.AutoMapper.AutoMapperConfiguration
using AutoMapper;
namespace Core.Infrastructure.AutoMapper
{
/// <summary>
/// 【自动映射配置--类】
/// <remarks>
/// 摘要:
/// 通过该类中的成员方法例化当前类中的两个静态属性成员:
/// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
/// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
/// </remarks>
/// </summary>
public static class AutoMapperConfiguration
{
/// <summary>
/// 【映射器】
/// <remarks>
/// 摘要:
/// 获取/设置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
/// </remarks>
/// </summary>
public static IMapper Mapper { get; private set; }
/// <summary>
/// 【映射配置】
/// <remarks>
/// 摘要:
/// 获取/设置两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
/// </remarks>
/// </summary>
public static MapperConfiguration MapperConfiguration { get; private set; }
/// <param name="config">两个不同类型实例赋值操作之间的映射规则实例。</param>
/// <summary>
/// 【实例化】
/// <remarks>
/// 摘要:
/// 通过该方法实例化当前类中的两个静态属性成员:
/// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
/// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
/// </remarks>
/// </summary>
public static void Init(MapperConfiguration config)
{
//获取两个不同类型实例赋值操作之间的映射规则实例。
MapperConfiguration = config;
//根据映射规则实例,获取与之相应的赋值操作映射器实例,为两个指定实例之间赋值操作提供实例支撑。
Mapper = config.CreateMapper();
}
}
}
4 Core.Infrastructure.Engine.AddAutoMapper
/// <summary>
/// 【添加自动映射】
/// <remarks>
/// 摘要:
/// 通过该类方法例化当前类中的两个静态属性成员:
/// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
/// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
/// </remarks>
/// </summary>
protected virtual void AddAutoMapper()
{
//从单例实例的字典成员实例中获取获取Web应用程序域类型查找器实例。
var typeFinder = Singleton<ITypeFinder>.Instance;
//获取继承于“IOrderedMapperProfile”的所有具体实现类的类型实例。
var mapperConfigurations = typeFinder.FindClassesOfType<IOrderedMapperProfile>();
//通过反射方式把继承于“IOrderedMapperProfile”的所有具体实现类进行实例化操作。
var instances = mapperConfigurations
.Select(mapperConfiguration => (IOrderedMapperProfile)Activator.CreateInstance(mapperConfiguration))
.OrderBy(mapperConfiguration => mapperConfiguration!.Order);
//依次实例化两个指定实例之间赋值操作映射规则。
var config = new MapperConfiguration(cfg =>
{
foreach (var instance in instances)
{
cfg.AddProfile(instance!.GetType());
}
});
// 实例化两个实例,
// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
AutoMapperConfiguration.Init(config);
}
5 重构Core.Infrastructure.Engine.ConfigureServices
public virtual void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
//把“Engine”实例存储到单例实例的字典成员实例中。
services.AddSingleton<IEngine>(this);
//从单例实例的字典成员实例中获取获取Web应用程序域类型查找器实例。
var typeFinder = Singleton<ITypeFinder>.Instance;
//获取继承于“IStartup”的所有具体实现类的类型实例。
var startupConfigurations = typeFinder.FindClassesOfType<IStartup>();
//通过反射方式把继承于“IStartup”的所有具体实现类进行实例化操作。
var instances = startupConfigurations
.Select(startup => (IStartup)Activator.CreateInstance(startup))
.OrderBy(startup => startup!.Order);
//把继承于“IStartup”的所有具体实现类的实例,依赖注入到.Net(Core)内置依赖注入容器实例中。
foreach (var instance in instances)
instance!.ConfigureServices(services, configuration);
services.AddSingleton(services);
// 把两个实例注入到内置容器中,
// 1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。
// 2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。
AddAutoMapper();
}
7 WebApi.Infrastructure.AutoMapper.MapperConfiguration
using AutoMapper;
using AutoMapper.Internal;
using Core.Domain.Users;
using Core.Infrastructure.AutoMapper;
using WebApi.Models;
namespace WebApi.Infrastructure.AutoMapper
{
/// <summary>
/// 【自动映射配置--类】
/// <remarks>
/// 摘要:
/// 通过该类中拷贝构造方法,对当前程序中的两个指定实例之间赋值操作映射规则,及其赋值操作进行实例化,并对它们进行集中管理。
/// </remarks>
/// </summary>
public class MapperConfiguration : Profile, IOrderedMapperProfile
{
#region 拷贝构造方法
/// <summary>
/// 【拷贝构造方法】
/// <remarks>
/// 摘要:
/// 通过该拷贝构造方法,对当前程序中的两个指定实例之间赋值操作映射规则,及其赋值操作进行实例化,并对它们进行集中管理。
/// </remarks>
/// </summary>
public MapperConfiguration()
{
CreateConfigMaps();
//在“ForAllMaps”方法为两个指定实例执行赋值操作时为特定赋值操作定义相应的映射规则(例如:“Ignore”,即在两个指定实例执行赋值操作时,忽略指定的属性成员实例)。
this.Internal().ForAllMaps((mapConfiguration, map) =>
{
});
}
#endregion
#region 属性
/// <summary>
/// 【顺序】
/// <remarks>
/// 摘要:
/// 继承于“IOrderedMapperProfile”接口的所有的具体实现类,被实例化时顺序;即在通过该接口批量实例化所有的具体实现类时,将按照指定具体实现类该属性成员值的排序顺序,依次的获取这些具体实现类的实例。
/// </remarks>
/// </summary>
public int Order => 0;
#endregion
#region 方法--私通/保护
/// <summary>
/// 【新建配置映射】
/// <remarks>
/// 摘要:
/// 该方法用于对无特定映射规则的两个指定实例之间的赋值操作定义进行集中管理。
/// </remarks>
/// </summary>
protected virtual void CreateConfigMaps()
{
CreateMap<RoleTestModel, Role> ();
}
#endregion
}
}
8 WebApi.Infrastructure.AutoMapper.Extensions.MappingExtensions
using Core.Infrastructure.AutoMapper;
namespace WebApi.Infrastructure.AutoMapper.Extensions
{
/// <summary>
/// 【映射扩展--类】
/// <remarks>
/// 摘要:
/// 该类中方法成员通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。
/// </remarks>
/// </summary>
public static class MappingExtensions
{
/// <typeparam name="TDestination">泛型类型实例(另1个指定类型实例,该类型实例为被赋值操作,提供实例支撑)。</typeparam>
/// <param name="source">泛型实例这里特指:1个指定类的1个指定实例,该实例为赋值操作提供数据源。</param>
/// <summary>
/// 【映射】
/// <remarks>
/// 摘要:
/// 该方法通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。
/// </remarks>
/// <returns>
/// 返回:
/// 被赋值后的另1个指定类型的1个指定实例。
/// </returns>
/// </summary>
public static TDestination Map<TDestination>(this object source)
{
return AutoMapperConfiguration.Mapper.Map<TDestination>(source);
}
/// <typeparam name="TSource">泛型类型实例(1个指定类型实例,该类型实例为赋值操作,提供数据支撑)。</typeparam>
/// <typeparam name="TDestination">泛型类型实例(另1个指定类型实例,该类型实例为被赋值操作,提供实例支撑)。</typeparam>
/// <param name="source">1个指定类的1个指定实例,该实例为赋值操作提供数据源。</param>
/// <param name="destination">另1个指定类的1个指定实例,该实例为赋值操作提供转换目标。</param>
/// <summary>
/// 【映射到】
/// <remarks>
/// 摘要:
/// 该方法通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。
/// </remarks>
/// <returns>
/// 返回:
/// 被赋值后的另1个指定类型的1个指定实例。
/// </returns>
/// </summary>
public static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)
{
return AutoMapperConfiguration.Mapper.Map(source, destination);
}
}
}
9 WebApi.Controllers.AutoMapperTestController
using Core.Domain.Users;
using Core.Infrastructure.AutoMapper;
using Microsoft.AspNetCore.Mvc;
using WebApi.Infrastructure.AutoMapper.Extensions;
using WebApi.Models;
namespace WebApi.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class AutoMapperTestController : ControllerBase
{
[HttpGet]
public async Task<MessageModel<bool>> AdminMapperTestAsync()
{
RoleTestModel _roleTestModel = new RoleTestModel() { Id = 1, Name = "a", IsActive = true, Remark = "aa" };
Role role = AutoMapperConfiguration.Mapper.Map<Role>(_roleTestModel);
RoleTestModel _roleTestModel_1 = new RoleTestModel() { Id = 2, Name = "b", IsActive = true, Remark = "bb" };
Role role_1 = MappingExtensions.Map<Role>(_roleTestModel_1);
RoleTestModel _roleTestModel_2 = new RoleTestModel() { Id = 3, Name = "c", IsActive = true, Remark = "cc" };
Role role_2 = MappingExtensions.MapTo<RoleTestModel, Role>(_roleTestModel_2, new Role());
List<RoleTestModel> _roleTestModelList = new List<RoleTestModel>() { _roleTestModel, _roleTestModel_1, _roleTestModel_2 };
List<Role> _roleList = new List<Role>();
_roleList = AutoMapperConfiguration.Mapper.Map<List<Role>>(_roleTestModelList);
List<Role> _roleList_1 = new List<Role>();
_roleList_1 = MappingExtensions.Map<List<Role>>(_roleTestModelList);
List<Role> _roleList_2 = new List<Role>();
_roleList_2 = MappingExtensions.MapTo<List<RoleTestModel>, List<Role>>(_roleTestModelList, new List<Role>());
return null;
}
}
}
对以上功能更为具体实现和注释见:230206_026shopDemo(自动赋值映射操作中间件AutoMapper)。