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. K3CLOUD表关联

    销售订单关联发货通知单 销售订单表 T_SAL_ORDER A T_SAL_ORDERENTRY B T_SAL_ORDERENTRY_LK C 发货通知单表 T_SAL_DELIVERYNOTICE ...

  2. [Windows] Access SMBIOS

    SMBIOS architecture System Management BIOS (SMBIOS) is the premier standard for delivering managemen ...

  3. Derby 命令

    SHOW [ TABLES | VIEWS | PROCEDURES | FUNCTIONS | SYNONYMS ] { IN sche -- 列出表.视图.过程.函数或同义词 SHOW INDEX ...

  4. Qt char * 与 const char * 的转换

    char *ch1="hello11"; const char *ch2="hello22"; ch2 = ch1;//不报错,但有警告 ch1 = (char ...

  5. zabbix的MariaDB数据库改变存储位置

    #创建 mkdir /公司缩写/mysql   #停止数据库服务 systemctl status mariadb.service systemctl stop mariadb.service   # ...

  6. ionic3 生命周期钩子

    ionViewDidLoad 页面加载完成触发,这里的"加载完成"指的是页面所需的资源已经加载完成,但还没进入这个页面的状态(用户看到的还是上一个页面). 需要注意的是它是一个很傲 ...

  7. python开发之Pandas

    正确的对DataFrame reverse运算 data.reindex(index=data.index[::-]) or simply: data.iloc[::-] will reverse y ...

  8. 使用内网映射工具Holer将本地的Web应用映射到公网上访问

    Holer exposes local servers behind NATs and firewalls to the public internet over secure tunnels. Su ...

  9. java使用jackson生成和解析JSON

    java使用jackson生成和解析JSON 1.导包 2.生成json和解析json package test; import com.fasterxml.jackson.core.JsonProc ...

  10. html解析过程

    Web页面运行在各种各样的浏览器当中,浏览器载入.渲染页面的速度直接影响着用户体验 简单地说,页面渲染就是浏览器将html代码根据CSS定义的规则显示在浏览器窗口中的这个过程.先来大致了解一下浏览器都 ...