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. bug_ warning: control reaches end of non-void function

    摘要 在leetcode上编译时,它显示我编译错误 warning: control reaches end of non-void function 它的意思是:控制到达非void函数的结尾.就是说 ...

  2. C++ this指针详解(精辟)

    this 是 C++ 中的一个关键字,也是一个 const 指针,它指向当前对象,通过它可以访问当前对象的所有成员. 所谓当前对象,是指正在使用的对象.例如对于stu.show();,stu 就是当前 ...

  3. 学习python-20191208(1)-Python Flask高级编程开发鱼书_第03章_数据与flask路由

    视频01: 略...... ———————————————————————————————————————————————————————————— 视频02: 搜索需要外部数据源,也就是需要外部的A ...

  4. sqlserver中的数据导到mysql相关

    一.在sqlserver中生成数据表脚本,粘贴到记事本中,如下语法要进行替换 1.int IDENTITY (1, 1) NOT NULL——>id int unsigned NOT NULL ...

  5. 配置gitlab(备忘)

    已经配置好github的基础上,clone gitlab 地址git status 显示改变了的文件但是webstorm文件颜色不改变问题的解决:VCS->git-->remotes--& ...

  6. 转: zabbix3.2.1安装graphtrees插件

    转自 : http://blog.csdn.net/liang_baikai/article/details/53542317 graphtree介绍 由于zabbix的图像显示一块不太友好,图像没法 ...

  7. jsPDF

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. SWUST OJ Gold Nuggets Distribution(0490)

    Gold Nuggets Distribution(0490) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 421 Accepte ...

  9. Leetcode回溯相关题目Python实现

    1.46题,全排列 https://leetcode-cn.com/problems/permutations/ class Solution(object): def permute(self, n ...

  10. 正则提取关键字符-python代码实现

    原文地址:http://www.bugingcode.com/blog/python_re_extraction_key.html 关于python的正则使用在以前的文章中 http://www.bu ...