ABP官方文档(十三)【对象之间的映射】
2.7 ABP公共结构 - 对象之间的映射
2.7.1 简介
我们通常需要在近似的对象之间进行映射处理。这是一个重复且枯燥无味的工作,通常来说两个需要相互映射的对象之间有近似的或者相同的属性。思考一下这样一个案例:应用服务的方法:
public class UserAppService : ApplicationService
{private readonly IRepository<User> _userRepository;public UserAppService(IRepository<User> userRepository){_userRepository = userRepository;}public void CreateUser(CreateUserInput input){var user = new User{Name = input.Name,Surname = input.Surname,EmailAddress = input.EmailAddress,Password = input.Password};_userRepository.Insert(user);}
}
在这里,User是一个简单的实体;CreateUserInput是一个简单的DTO。从给定的输入对象,我们需要使用它来创建一个User实体。在真实的环境中User实体会有更多的属性,手动创建这个实体会变得枯燥无味且易出错。如果我们想要添加新的属性到User和CreateUserInput的时候,这会变得很复杂,我们应该改变这个映射代码,使映射更简单。
我们可以使用一个类库来实现自动映射。AutoMapper是最好的处理对象到对象之间映射的类库之一。ABP中定义了 IObjectMapper 接口,抽象了映射功能。在Abp.AutoMapper包中,我们实现了该接口来使用AutoMapper。
2.7.2 IObjectMapper 接口
IObjectMapper简单的抽象出了对象到对象之间映射的方法。我们可以使用更简单的代码实现上面提到的映射功能:
public class UserAppService : ApplicationService
{private readonly IRepository<User> _userRepository;private readonly IObjectMapper _objectMapper;public UserAppService(IRepository<User> userRepository, IObjectMapper objectMapper){_userRepository = userRepository;_objectMapper = objectMapper;}public void CreateUser(CreateUserInput input){var user = _objectMapper.Map<User>(input);_userRepository.Insert(user);}
}
Map 是一个简单的具有类型声明的泛型占位符的方法,可以将一个对象映射为另一个对象。Map方法的重载方法可以映射一个对象到一个 已存在 的对象。假设我们有了一个User实体,但是我们想通过DTO来更新用户实体的某些属性:
public void UpdateUser(UpdateUserInput input)
{var user = _userRepository.Get(input.Id);_objectMapper.Map(input, user);
}
2.7.3 AutoMapper 集成
在Abp.AutoMapper包中,我们实现了IObjectMapper接口并提供了一些辅助功能。
安装
首先,需要安装 Abp.AutoMapper 到你的项目中:
Install-Package Abp.AutoMapper
然后添加 AbpAutoMapperModule 作为依赖项到你定义的模块类中:
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{...
}
这样你就可以在代码中安全的注入和使用IObjectMapper接口了。如果有需要,你也可以使用AutoMapper自己的API。
创建映射
在使用映射之前,AutoMapper默认需要定义类之间的映射关系。在使用的时候你可以查询它的文档。但是使用ABP会使映射关系的创建更简单且模块化。
自动映射特性
大多数时候你只想对类进行直接(按约定的方式)映射。在这种情况下,你可以使用 AutoMap,AutoMapFrom 以及 AutoMapTo 特性。例如:在上面的例子中,我们将 CreateUserInput 映射到 User,我们可以使用 AutoMapTo 特性来实现。如下所示:
[AutoMapTo(typeof(User))]
public class CreateUserInput
{public string Name { get; set; }public string Surname { get; set; }public string EmailAddress { get; set; }public string Password { get; set; }
}
AutoMap特性可以在两个类型之间实现彼此之间的相互映射。但是在这个例子中,我们只需要将 CreateUserInput 映射到 User。所以我们可以使用 AutoMapTo。
自定义映射
在某些情况下,简单的映射不能满足需求。例如:两个类中的属性名字可能稍微有些不同或者你想忽略某些属性的映射。在这种情况下,你可以直接使用 AutoMapper 的 API 来实现映射。Abp.AutoMapper 包中的定义的 API 使自定义映射更加模块化。
假设在映射的时候,我们想忽略Password属性,并使 EmailAddress 属性映射到 User 的Email 属性。我们可以像下面一样来实现映射关系:
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{public override void PreInitialize(){Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>{config.CreateMap<CreateUserInput, User>().ForMember(u => u.Password, options => options.Ignore()).ForMember(u => u.Email, options => options.MapFrom(input => input.EmailAddress));});}
}
AutoMapper拥有更多的选项和能力来做对象之间的映射。详情请查询文档。
MapTo扩展方法
如上面所述,我们建议注入并使用IObjectMapper接口。这使我们的项目尽可能的不依赖AutoMapper。这也使单元测试更简单,因为在单元测试的时候我们可以替换掉映射依赖。
在 Abp.AutoMapper 中也有 MapTo 的扩展方法,我们可以不注入IObjectMapper接口,使用它将任意对象映射为其它对象。如下所示:
public class UserAppService : ApplicationService
{private readonly IRepository<User> _userRepository;public UserAppService(IRepository<User> userRepository){_userRepository = userRepository;}public void CreateUser(CreateUserInput input){var user = input.MapTo<User>();_userRepository.Insert(user);}public void UpdateUser(UpdateUserInput input){var user = _userRepository.Get(input.Id);input.MapTo(user);}
}
在 Abp.AutoMapper 的名称空间中定义了 MapTo 的扩展方法。首先你得在你的代码中导入该名称空间。
由于MapTo扩展方法是静态的,它使用的是AutoMapper的静态实例。对于应用程序代码这是简单且有效的,但是静态配置在单元测试的时候会有问题,因为在单元测试的时候,会在各个单元测试之间共享映射关系。
单元测试
我们想隔离各个测试单元。为了实现该功能,我们应该使我们的项目遵循下面规则:
- 使用IObjectMapper接口,而不使用MapTo静态方法。
- 配置 Abp.AutoMapper 模块使用本地Mapper实例(在依赖注入时,注册为单例模式)而不是静态实例(Abp.AutoMapper 默认使用静态 Mapper.Instance实例,这样我们就可以使用MapTo扩展方法来实现对象之间的映射,如上面例子所示)。
Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;
预定义映射
LocalizableString -> string
Abp.AutoMapper模块中定义了一个映射方法:将LocalizableString(或者ILocalizableString)对象转换为string对象。它使用 ILocalizationManager接口来实现转换。所以在处理任意类的映射时,可本地化属性被自动的本地化。
注入IMapper
你可以直接使用AutoMapper的IMapper对象,而不是使用IObjectMapper接口。这样的话,在你的类中注入IMapper并使用它。Abp.AutoMapper包注册IMapper作为依赖注入单例。
ABP官方文档(十三)【对象之间的映射】相关推荐
- Mybatis官方文档中的(XML映射文件)模块(半途凉了)
Mybatis官方文档中的(XML映射文件)模块(半途凉了) 一.XML映射器属性的介绍 Mybatis的真正强大之处在于它的语句映射.他即可以自动的映射数据库中的字段和对象的属性. SQL映射文件有 ...
- ABP官方文档(三)【模块系统】
1.3 ABP总体介绍 - 模块系统 1.3.1 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块.在通常情况下,一个程序集就可以看成是一个模块.在ABP框架中, ...
- ajax访问带token abp,ABP官方文档(三十八)【AJAX API】
6.6 ABP表现层 - AJAX API 6.6.2.1 AJAX操作问题 现代的应用经常会使用AJAX,尤其是单页应用,几乎是和服务器通信的唯一手段,执行AJAX通常会有以下步骤: 基本上:为了执 ...
- ABP官方文档(十六)【值对象】
3.2 ABP领域层 - 值对象 3.2.1 简介 用来描述领域的特殊方面.且没有标识符的一个对象,叫做值对象. 实体有自己的唯一标识,而值对象是没有标识的.如果两个实体的标识是不同的,那么它们是两个 ...
- ABP官方文档(四十四)【后台作业和后台工人】
7.1 ABP后台服务 - 后台作业和后台工人 7.1.1 简介 ABP提供了后台作业和后台工人,来执行应用程序中的后台线程的某些任务. 7.1.2 后台作业 由于各种各样的原因,你需要后台作业以队列 ...
- ABP官方文档(四十一)【ASP.NET Core】
6.8 ASP.NET Core 6.8.1 简介 这篇文档是对ABP中集成的ASP.NET Core的描述.ASP.NET 集成是被实现在 Abp.AspNetCore 中. 迁移到ASP.NET ...
- ABP官方文档(三十)【动态WebApi层】
5.2 ABP表现层 - 动态WebApi层 5.2.1 建立动态WebApi控制器 这是一篇关于ASP.NET Web API的文档.如果你对ASP.NET感兴趣,请阅读ASP.NET Core文档 ...
- ABP官方文档(五)【多租户】
1.5 ABP总体介绍 - 多租户 1.5.1 什么是多租户 维基百科:"软件多租户是指一个软件架构的实例软件运行在一个服务器上,但存在多个租户.租户是一组共享一个公共的用户访问特定权限的软 ...
- ABP官方文档(四十五)【集成Hangfire】
7.2 ABP后台服务 - 集成Hangfire 7.2.1 简介 Hangfire是一个综合性的后台作业管理工具.你可以用Hangfire来替换ABP中默认实现的后台作业管理者.你可以对Hangfi ...
最新文章
- (转)android 在电脑上显示真机屏幕
- Invert Binary Tree
- 15必须阅读Java 8教程
- javascript的浏览器Bom详解,window、location、history对象
- 各自然带代表植被_植被垂直带谱?水与热之间的较量。
- 面试题:彻底搞懂 Cookie 和 Session
- QT嵌入式之_QT介绍_安装_以及环境变量配置---QT嵌入式图形框架工作笔记001
- ubuntu git cntlm 代理 不能下载
- Jfinal中使用Ueditor遇到的问题【解决办法】
- 2021-06-22列表样式与背景图片
- 函数求和公式计算机出库入库,出库入库表格函数公式.doc
- python数据分析的常用方法_16种常用的数据分析方法汇总
- 代码记录:易语言中精易模块的json文本数据生成
- HBuilderX前端html功能应用
- 利用MATLAB求解积分
- 微信小程序进度条样式_详解微信小程序——自定义圆形进度条
- NPOI写Excel,Microsoft.Office.Interop.excel.dll 转换Excel为PDF
- On the Factory Floor: ML Engineering for Industrial-Scale Ads Recommendation Models笔记
- 小试牛刀—猜数字游戏
- python math ceil_python中math.ceil什么意思