ABP框架系列之四十二:(Object-To-Object-Mapping-对象映射)
Introduction
It's a common to map a similar object to another object. It's also tedious and repeating since generally both objects (classes) may have similar/same properties mapped to each other. Think on a typical application servicemethod below:
将相似的对象映射到另一个对象是很常见的。这也是乏味和重复的,因为一般两个对象(类)可能具有相似的/相同的属性映射到彼此。想象在一个典型的应用服务的方法:
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);
}
}
CreateUserInput is a simple DTO and User is a simple entity here. We manually created a User entity from given input. User entity will have much more properties in a real world application and manually creating it will become tedious and error-prone. Also, we should change the mapping code when we want to add new properties to User and CreateUserInput.
createuserinput是一个简单的DTO和用户这是一个简单的实体。我们从给定输入手动创建了一个用户实体。用户实体在实际应用程序中具有更多的属性,手工创建它将变得单调乏味,容易出错。同时,我们应该改变映射的代码时,我们要对用户和createuserinput添加新的属性。
We can use a library to make this mapping automatically. AutoMapper is one of the best libraries for object to object mapping. ASP.NET Boilerplate defines IObjectMapper interface to abstract it and implements this interface using AutoMapper in Abp.AutoMapper package.
我们可以使用一个库来自动绘制这个映射。AutoMapper是一个对象到对象的映射最好的库。ASP.NET的模板定义iobjectmapper接口抽象和实现这个接口使用AutoMapper Abp.AutoMapper包。
IObjectMapper Interface
IObjectMapper is a simple abstraction that has Map methods to map an object to another. We can write the sample code above as like below:
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 is a simple method gets the source object and creates a new destination object with the type declared as the generic parameter (User in this sample). Map method has an overload to map an object to an existing object. Assume that we already have a User entity and want to update it's properties by an object:
map是获取源对象并创建一个新的目标对象的简单方法,该对象声明为泛型参数(本示例中的用户)。映射方法具有将对象映射到现有对象的重载。假设我们已经有一个用户实体,并且想通过对象更新它的属性:
public void UpdateUser(UpdateUserInput input)
{
var user = _userRepository.Get(input.Id);
_objectMapper.Map(input, user);
}
AutoMapper Integration
Abp.AutoMapper nuget package (module) implements IObjectMapper and provides additional features.
Installation
First, install Abp.AutoMapper nuget to your project:
Install-Package Abp.AutoMapper
Then add a dependency for AbpAutoMapperModule to your module definition class:
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyModule : AbpModule
{
...
}
Then you can safely inject and use IObjectMapper in your code. You can also use AutoMapper's own API when you need.
Creating Mappings
AutoMapper requires to define mappings between classes (by default) before using the mapping. You can see it's own documentation for details on mapping. ASP.NET Boilerplate makes it a bit easier and modular.
AutoMapper需要定义之间的映射类(默认)在使用映射。关于映射的详细信息,您可以看到它自己的文档。ASP.NET样板使它更简单和模块化。
Auto Mapping Attributes(自动映射特性)
Most of time you only want to directly (and conventionally) map classes. In that case, you can use AutoMap, AutoMapFrom and AutoMapTo attributes. For instance, as we want to map CreateUserInput class to User class in the sample above, we can use AutoMapTo attribute as shown below:
[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 attribute maps two classes in both direction. But in this sample, we only need to map from CreateUserInput to User, so we used AutoMapTo.
Custom Mapping(自定义映射)
Simple mapping may not be suitable in some cases. For instance, property names of two classes may be a little different or you may want to ignore some properties during the mappping. In such cases you should directly use AutoMapper's API to define the mapping. Abp.AutoMapper package defines API to make this custom mapping stuff more modular.
在某些情况下,简单映射可能不合适。例如,两类属性名称可能有所不同,或者你可能想忽略的一些性质在映射。在这种情况下,你应该直接使用AutoMapper的API来定义映射。abp.automapper包定义API进行自定义映射的东西更加模块化。
Assume that we want to ignore Password on mapping and User has Email property for email address. We can define mapping as shown below:
假设我们希望忽略映射中的密码,用户拥有电子邮件地址的电子邮件属性。我们可以定义映射如下图所示:
[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 has much more options and abilities for object to object mapping. See it's documentation for more.
MapTo Extension Methods(MapTo 扩展方法)
It's suggested to inject and use IObjectMapper interface as defined before. This makes our project independent from AutoMapper as much as possible. It also makes unit testing easier since we can replace (mock) the mapping in unit tests.
Abp.AutoMapper module also defines MapTo extension methods which can be used on any object to map it to another object without injecting IObjectMapper. Example usage:
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);
}
}
MapTo extension methods are defined in Abp.AutoMapper namespace, so you first import this namespaces into your code file.
Since MapTo extension methods are statics, they use AutoMapper's static instance (Mapper.Instance). This is simple and fine for the application code, but can have problems in unit tests since static configuration and mapper is shared among different tests and they may effect each other.
由于扩展方法是静态的,他们使用AutoMapper的静态实例(制图。实例)。这对于应用程序代码来说是简单而精细的,但是单元测试可能会有问题,因为静态配置和映射器在不同的测试中共享,它们可能相互影响。
Unit Tests
We want to isolate tests from each others. To do that, we should design our project with the following rules:
我们希望从彼此之间分离测试。要做到这一点,我们应该按照以下规则来设计我们的项目:
1. Always use IObjectMapper, not use MapTo extension methods.
2. Configure Abp.AutoMapper module to use local Mapper instance (registered as singleton to dependency injection) rather than the static one (Abp.AutoMapper uses the static Mapper.Instance by default to allow to use MapTo extension methods defined above):
Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;
Pre Defined Mappings(预先定义的映射)
LocalizableString -> string
Abp.AutoMapper module defines a mapping to convert LocalizableString (or ILocalizableString) objects to string objects. It makes the conversion using ILocalizationManager, so localizable properties are automatically localized during the mapping process of any class.
abp.automapper模块定义转换localizablestring映射(或ilocalizablestring)对象的字符串对象。它使转换使用ilocalizationmanager,所以可本地化的属性自动定位的任何类别的映射过程。
Injecting IMapper
You may need to directly use AutoMapper's IMapper object instead of IObjectMapper abstraction. In that case, just inject IMapper in your classes and use it. Abp.AutoMapper package registers IMapper to dependency injectionas singleton.
ABP框架系列之四十二:(Object-To-Object-Mapping-对象映射)的更多相关文章
- ABP框架系列之五十二:(Validating-Data-Transfer-Objects-验证数据传输对象)
Introduction to validation Inputs of an application should be validated first. This input can be sen ...
- ABP框架系列之四十:(Notification-System-通知系统)
Introduction Notifications are used to inform users on specific events in the system. ASP.NET Boiler ...
- ABP框架系列之四十九:(Startup-Configuration-启动配置)
ASP.NET Boilerplate provides an infrastructure and a model to configure it and modules on startup. A ...
- ABP框架系列之三十二:(Logging-登录)
Server Side(服务端) ASP.NET Boilerplate uses Castle Windsor's logging facility. It can work with differ ...
- ABP框架系列之四十六:(Setting-Management-设置管理)
Introduction Every application need to store some settings and use these settings in somewhere in th ...
- ABP框架系列之四十八:(Specifications-规范)
Introduction Specification pattern is a particular software design pattern, whereby business rules c ...
- ABP框架系列之四十四:(OWIN)
If you are using both of ASP.NET MVC and ASP.NET Web API in your application, you need to add Abp.Ow ...
- ABP框架系列之十二:(Audit-Logging-审计日志)
Introduction Wikipedia: "An audit trail (also called audit log) is a security-relevant chronolo ...
- ABP框架系列之四十五:(Quartz-Integration-Quartz-集成)
Introduction Quartz is a is a full-featured, open source job scheduling system that can be used from ...
随机推荐
- Linux背背背(2)
目录: 1.简单命令 2.目录切换命令 3.扩展命令 简单命令 ls 语法1:#ls [路径] 表示列出指定路径下的文件夹和文件的名字,如果路径没有指定则列出当前路径下的 语法2 ...
- 全面了解Ngnix的主要应用的场景
前言 本文只针对 Nginx 在不加载第三方模块的情况能处理哪些事情,由于第三方模块太多所以也介绍不完,当然本文本身也可能介绍的不完整,毕竟只是我个人使用过和了解到过得.所以还请见谅,同时欢迎留言交流 ...
- linux服务之ntp与dns篇
ntp复习: 简介:对于计算机时间的同步管理操作服务器 部署:(服务端和客户端或者说集群) 1.服务端下载ntp 2.打开配置文件/etc/ntp.conf: server 127.127.1.0 ...
- Android Studio 加载网络图片
Android Studio是基于gradle的一个Android开发软件,在引用网络图片的时候需要连接第三方库,这里介绍 引用glide的方法. 一.在github页面搜索glide,点击第一个 二 ...
- 性能测试Jmeter扩展学习-添加自定义函数
我们在使用jmeter的时候有时候会碰到jmeter现有插件或功能也无法支持的场景,比如前端加密,此时我们就需要自己手动编写函数并导入了,下面就是手动修改并导入的过程. 首先我们需要下载jmeter源 ...
- maven的单元测试中没有
原因:BaseTest没有找到单元测试造成的 增加一个空的单元测试 @Testpublic void testNothing(){} 异常现象:在maven项目执行mvn install 或mvn t ...
- java学习--"==”和 equals
== 比较的是两个值是否相等 这里的值有可能是基础类型的值,也有可能是指向对象的引用 equals方法如何比较,要看这个类的equals方法是如何定义的 基类Object类的equals方法比较的是 ...
- 从performance_schema中查看MySQL活动Session的详细执行信息
本文出处:http://www.cnblogs.com/wy123/p/7851294.html 在做数据库的异常诊断的时候,之前在SQL Server上的时候,最主要的参考信息之一就是去看当前的活动 ...
- python-imaging-tk : Depends: python-imaging (= 1.1.7-4ubuntu0.12.04.3) but 3.1.2-0ubuntu1.1 is to be installed E: Unable to corre
最近,将电脑主机升级到ubuntu16.04,但是需要用到 python-imaging-tk,先是报错: import PIL.ImageTk as ImageTkImportError: No m ...
- 大数据入门到精通14--hive 对 字符串的操作
一.基本操作 concat(string,string,string)concat_ws(string,string,string)select customer_id,concat_ws(" ...