1.什么是AutoMapper?

AutoMapper是一个对象-对象映射器。对象-对象映射通过将一种类型的输入对象转换为另一种类型的输出对象来工作。使AutoMapper变得有趣的是,它提供了一些有趣的约定,免去用户不需要了解如何将类型A映射为类型B。只要类型B遵循AutoMapper既定的约定,就需要几乎零配置来映射两个类型。映射代码虽然比较无聊,但是AutoMapper为我们提供简单的类型配置以及简单的映射测试,而映射可以在应用程序中的许多地方发生,但主要发生在层之间的边界中,比如,UI /域层之间或服务/域层之间。一层的关注点通常与另一层的关注点冲突,因此对象-对象映射导致分离的模型,其中每一层的关注点仅会影响该层中的类型。

2.如何在Core上面使用AutoMapper组件?

先在Startup.ConfigureServices注入AutoMapper组件服务,然后在Startup.Configure上获取AutoMapper服务配置扩展类创建对象-对象映射关系,为了好统一管理代码,可以新建一个AutoMapperExtension静态类,把以下代码封装一下:

public static class AutoMapperExtension
{
/// <summary>
/// 新增自动映射服务
/// </summary>
/// <param name="service"></param>
/// <returns></returns>
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
#region 方案一
//注册AutoMapper配置扩展类服务
services.TryAddSingleton<MapperConfigurationExpression>();
//注册AutoMapper配置扩展类到AutoMapper配置服务去
services.TryAddSingleton(serviceProvider =>
{
var mapperConfigurationExpression = serviceProvider.GetRequiredService<MapperConfigurationExpression>();
var mapperConfiguration = new MapperConfiguration(mapperConfigurationExpression);
mapperConfiguration.AssertConfigurationIsValid();
return mapperConfiguration;
});
//注入IMapper接口DI服务
services.TryAddSingleton(serviceProvider =>
{
var mapperConfiguration = serviceProvider.GetRequiredService<MapperConfiguration>();
return mapperConfiguration.CreateMapper();
});
return services;
#endregion
} /// <summary>
/// 使用自动映射配置扩展类
/// </summary>
/// <param name="applicationBuilder"></param>
/// <returns></returns>
public static IMapperConfigurationExpression UseAutoMapper(this IApplicationBuilder applicationBuilder)
{
//获取已注册服务AutoMapper配置扩展类
return applicationBuilder.ApplicationServices.GetRequiredService<MapperConfigurationExpression>();
}
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
......
//添加自动映射组件DI服务
services.AddAutoMapper();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
......
//注册组件之后,创建映射对象
  var expression = app.UseAutoMapper();
expression.CreateMap<Customer, CustomerDto>();
expression.CreateMap<Address, AddressDto>();
}

因为IMapper接口已经在ConfigureServices方法注入DI服务了,所以无需再重新注入,只需要直接使用IMapper调用其方法就可以:

public class BlogsController : Controller
{
private IMapper _iMapper { get; }
public BlogsController(IMapper iMapper)
{
_iMapper = iMapper;
}
// GET: Blogs
public async Task<IActionResult> Index()
{
//对象-对象数据传输
var dto = _iMapper.Map<CustomerDto>(CustomerInitialize());
......
}
//手动赋值客户对象数据
private Customer CustomerInitialize()
{
var _customer = new Customer()
{
Id = ,
Name = "Eduardo Najera",
Credit = 234.7m,
Address = new Address() { City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad." },
HomeAddress = new Address() { City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad." },
WorkAddresses = new List<Address>()
{
new Address() {City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad."},
new Address() {City = "izmir", Country = "turkey", Id = , Street = "konak"}
},
Addresses = new List<Address>()
{
new Address() {City = "istanbul", Country = "turkey", Id = , Street = "istiklal cad."},
new Address() {City = "izmir", Country = "turkey", Id = , Street = "konak"}
}.ToArray()
};
return _customer;
}
}

运行效果:

3.如果更加灵活使用AutoMapper组件?

相信在第二章节时候,相信大家都会发现一个问题,如果生产场景业务越来越庞大,需创建对应业务对象也会越来越多,如果面对这样的业务场景难道要在Configure方法里面创建越来越多的映射关系吗?例:

var expression = app.UseAutoMapper();
expression.CreateMap<A, ADto>();
expression.CreateMap<B, BDto>();
expression.CreateMap<C, CDto>();
expression.CreateMap<D, DDto>();
......

很显然这样子是不可行的,这样会导致后续代码越来越多,难以维护。那么现在让我们来解决这个问题。首先新建一个自动注入属性的AutoInjectAttribute密封类,具体代码如下:

public sealed class AutoInjectAttribute : Attribute
{
public Type SourceType { get; }
public Type TargetType { get; }
public AutoInjectAttribute(Type sourceType, Type targetType)
{
SourceType = sourceType;
TargetType = targetType;
}
}

新增这个AutoInjectAttribute密封类,目的是声明每个DTO对象(数据传输对象)与对应数据源对象是传输关系,方便在Configure里面自动注册创建映射关系,例:

//声明源对象,目标对象
[AutoInject(sourceType: typeof(Customer),targetType:typeof(CustomerDto))]
public class CustomerDto
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public AddressDto HomeAddress { get; set; }
public AddressDto[] Addresses { get; set; }
public List<AddressDto> WorkAddresses { get; set; }
public string AddressCity { get; set; }
}

然后创建一个自动注入AutoInjectFactory工厂类,检测运行中的程序集是否有AutoInjectAttribute属性声明,如果有则插入一个类型数据集中返回,目的是把所有声明需要映射DTO对象跟数据源对象自动创建映射关系:

public class AutoInjectFactory
{
public List<(Type, Type)> AddAssemblys
{
get
{
var assemblys =new List<Assembly>() { Assembly.GetExecutingAssembly() };
List<(Type, Type)> ConvertList = new List<(Type, Type)>();
foreach (var assembly in assemblys)
{
var atributes = assembly.GetTypes()
.Where(_type => _type.GetCustomAttribute<AutoInjectAttribute>() != null)
.Select(_type => _type.GetCustomAttribute<AutoInjectAttribute>());
foreach (var atribute in atributes)
{
ConvertList.Add((atribute.SourceType, atribute.TargetType));
}
}
return ConvertList;
}
}
}

在第2小节AutoMapperExtension静态类的AddAutoMapper方法内修改如下代码:

#region 方案二
//注入AutoMapper配置扩展类服务
services.TryAddSingleton<MapperConfigurationExpression>();
//注入自动注入工厂类服务
services.TryAddSingleton<AutoInjectFactory>();
//注入AutoMapper配置扩展类到AutoMapper配置服务去
services.TryAddSingleton(serviceProvider =>
{
var mapperConfigurationExpression = serviceProvider.GetRequiredService<MapperConfigurationExpression>();
//通过自动注入工厂类获取声明数据源对象与DTO对象自动创建映射关系
var factory = serviceProvider.GetRequiredService<AutoInjectFactory>();
foreach (var (sourceType, targetType) in factory.AddAssemblys)
{
mapperConfigurationExpression.CreateMap(sourceType, targetType);
}
var mapperConfiguration = new MapperConfiguration(mapperConfigurationExpression);
mapperConfiguration.AssertConfigurationIsValid();
return mapperConfiguration;
});
//注入IMapper接口DI服务
services.TryAddSingleton(serviceProvider =>
{
var mapperConfiguration = serviceProvider.GetRequiredService<MapperConfiguration>();
return mapperConfiguration.CreateMapper();
});
return services;
#endregion

再新增一个使用自动注入工厂类服务静态方法:

/// <summary>
/// 使用自动注入工厂类
/// </summary>
/// <param name="applicationBuilder"></param>
public static void UseAutoInject(this IApplicationBuilder applicationBuilder)
{
applicationBuilder.ApplicationServices.GetRequiredService<AutoInjectFactory>();
}

然后在Startup.ConfigureServices注入AutoMapper组件服务,然后在Startup.Configure上调用UseAutoInject静态方法,具体代码如下:

app.UseAutoInject();

运行效果:

从运行结果来看依然是这个酸爽!

参考文献:
AutoMapper

(28)ASP.NET Core AutoMapper组件的更多相关文章

  1. 笔记: ASP.NET Core视图组件

    视图组件 asp.net core mvc 提供了部分视图的新替代品:视图组件. 视图组件与分布视图的主要区别在于视图组件与控制器不相关.可使用在独立于单个控制器的场景,如:菜单导航.侧边栏.分页栏等 ...

  2. Blazor入门:ASP.NET Core Razor 组件

    目录 关于组件 组件类 静态资产 路由与路由参数 组件参数 请勿创建会写入其自己的组参数属性的组件 子内容 属性展开 任意参数 捕获对组件的引用 在外部调用组件方法以更新状态 使用 @ 键控制是否保留 ...

  3. asp.net core 视图组件(转)

    介绍视图组件 视图组件是 ASP.NET Core MVC 中的新特性,与局部视图相似,但是它们更加的强大.视图组件不使用模型绑定,只取决于调用它时所提供的数据.视图组件有以下特点: 渲染一个块,而不 ...

  4. asp.net core日志组件

    日志介绍 Logging的使用 1. appsettings.json中Logging的介绍 Logging的配置信息是保存在appsettings.json配置文件中的.因为之前介绍配置文件的时候我 ...

  5. asp.net core 视图组件化

    视图组件可以通过partial view或viewcomponent实现 partialview https://docs.microsoft.com/zh-cn/aspnet/core/mvc/vi ...

  6. asp.net core视图组件(ViewComponent)简单使用

    一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. 定义一个视图组件,如控制器一样,必须是公开,非嵌套,非抽象的类.一般,视图组件名称为类名去掉&qu ...

  7. Asp.Net core 视图组件ViewComponent

    视图组件 ViewComponent 最近用了一下视图组件,还挺方便的,如果遇到公共的部分,可以抽出来,写成视图组件,方便调用 先上图看一下效果:比如首页的4个画红框的地方是4个模块,有些地方可能要重 ...

  8. [转]asp.net core视图组件(ViewComponent)简单使用

    本文转自:http://www.cnblogs.com/dralee/p/6170496.html 一.组成: 一个视图组件包括两个部分,派生自ViewComponent的类及其返回结果.类似控制器. ...

  9. ASP NET Core ---Automapper

    官方文档:http://docs.automapper.org/en/stable/index.html 一.安装和配置: 二.使用: 1.建立 Profile文件: public class Map ...

随机推荐

  1. sql查询语句解析过程--根据网络资料整理

    查询语句: (8)SELECT(9)DISTINCT(11)<TopNum> <selectlist> (1)FROM<left_table> (3)<joi ...

  2. swift中的category,扩展

    1.创建选择 :swift file 2.名称:UIBarButtonItem-Extension 3.category,便利构造函数 extension UIColor { /* 1.extensi ...

  3. 吴裕雄--天生自然 JAVASCRIPT开发学习:JavaScript 对象 实例

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. LeetCode No.85,86,87

    No.85 MaximalRectangle 最大矩形 题目 给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积. 示例 输入: [ ["1", ...

  5. [LC] 54. Spiral Matrix

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  6. 【待填坑】LG_2467_[SDOI2010]地精部落

    不错的dp题...思维难度和码量成反比...

  7. <JZOJ5941>乘

    emmm还挺妙 不过我没想到qwq 考场上瞎写的还mle了心碎 把b分两..预处理下 O1询问qwq #include<cstdio> #include<iostream> # ...

  8. 851. spfa求最短路

    给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible. 数据保证不存在负权回路. 输入格式 ...

  9. python登陆接口编写

    #coding:utf-8 import getpass,sys i=0 j=0 while i<3: username=raw_input('username:') #输入用户名 life_1 ...

  10. Allenmind's Blog

    听说,Sass和Compass更配哟.来看看Compass的基本用法! 目录 Compass和Sass 安装Compass 项目初始化 编译 Compass的模块 Compass的Helper函数 一 ...