文档目录

本节内容:

简介

把一个对象映射到另一个相似的对象很常见,两个对象(类)具有相似或相同的属性,它们之间要互相映射,其实这项工作重复且无聊,考虑一个典型的应用服务方法,如下:

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是一个简单的数据传输对象,User是一个简单的实体,我们根据传入的input手工创建一个User实体,现实应用里User实体将会有更多的属性,手工创建它就会变得很无聊且容易出错,而且,当我们添加新的属性到User和CreateUserInput时,又需要修改映射的代码。

其实我们可以用一个类库来自动完成映射,AutoMapper是一个最好的对象到对象的映射类库,Abp中定义了IObjectMapper接口来抽象它,且在 Abp.AutoMapper包中实现了这个接口。

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是一个简单的方法,它获取源对象并且根据泛型参数给定的类型创建一个对应的新的目标对象(此示例中的User),Map有一个重载版本,它把一个对象映射到一个已存在的对象,假设我们已经有一个User实体,想根据另一个对象更新这个实体的属性:

public void UpdateUser(UpdateUserInput input)
{
var user = _userRepository.Get(input.Id);
_objectMapper.Map(input, user);
}

集成 AutoMapper

Abp.AutoMapper nuget包(模块)实现了IObjectMapper接口并且提供了额外功能。

安装

首先,安装Abp.AutoMapper nuget包到你的项目里:

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);
}
}

MapTo扩展方法定义在 Abp.AutoMapper 命名空间里,所以你需要先在你的代码里引入命名空间。

由于MapTo扩展方法是静态的,它们使用AutoMapper的静态实例(Mapper.Instance),这样对于应用代码来说,比较简单和好用,但是在单元测试里由于静态配置和映射是在不同的测试之间共享它,它们相互影响 ,可能会带来一些问题。

单元测试

我们想把每个单元测试独立开来,所以我们需要为我们的项目定义如下规则:

1.只使用IObjectMapper,不使用扩展方法MapTo.

2.配置Abp.AutoMapper 模块,使用局部的Mapper实例(用单例的方式注册到依赖注入)不用静态的(Abp.AutoMapper默认情况下,使用静态的Mapper.Instance,从而可以像上面那样使用MapTo扩展方法):

Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;

预定义的映射

LocalizableString -> string

Abp.AutoMapper模块定义了一个从LocalizableString (或 ILocalizableString) 对象到string对象的映射,它使用ILoclaizationManager进行转换,所以在映射过程中,可以本地化的属性会自动的本地化。

注入 IMapper

如果你需要注入AutoMapper的IMapper对象来代替IObjectMapper,就直接在你的类里注入IMapper并使用它,Abp.AutoMapper包把IMapper作为单例注册到了依赖注入系统里。

ABP文档 - 对象与对象之间的映射的更多相关文章

  1. JAVA对象和XML文档、原来他们之间还有这一出

    最近项目开发中遇到一个问题,访问接口不再通过url地址请求的方式,而是 通过socket发送xml格式的报文到指定服务器来进行信息的统一认证.. 因此组装xml格式的报文字符串以及解析服务器返回的xm ...

  2. XML解析之sax解析案例(二)使用sax解析把 xml文档封装成对象

    Demo1类: import java.io.File; import java.util.List; import javax.xml.parsers.SAXParser; import javax ...

  3. ABP文档笔记系列

    ABP文档笔记 - 模块系统 及 配置中心 ABP文档笔记 - 事件BUS ABP文档笔记 - 数据过滤 ABP文档笔记 - 规约 ABP文档笔记 - 配置.设置.版本.功能.权限 ABP文档笔记 - ...

  4. jQuery对标签、类样式、值、文档、DOM对象的操作

    jquery的标签属性操作 使用attr()方法对html标签属性进行操作,attr如果参数是一个参数,表示获取html标签的属性值,如果是两个参数则是设置标签属性名以及对象的属性值 .prop()适 ...

  5. excel文档中嵌入对象(excel、word等)

    //测试环境office2016.office365 string InsertPath= @"E:\\新建文件夹\\2.xls";//插入的文档路径 string openfil ...

  6. ABP文档 - 后台作业和工作者

    文档目录 本节内容: 简介 后台作业 关于作业持久化 创建一个后台作业 在队列里添加一个新作业 默认的后台作业管理器 后台作业存储 配置 禁用作业执行 Hangfire 集成 后台工作者 创建一个后台 ...

  7. ABP文档 - 导航

    文档目录 本节内容: 创建菜单 注册导航供应器 显示菜单 每个web应用都有一些菜单用来在页面/屏幕之间导航,ABP提供了一个通用的基础框架创建并显示菜单给用户. 创建菜单 一个应用可能由不同模块组成 ...

  8. ABP文档 - Javascript Api - AJAX

    本节内容: AJAX操作相关问题 ABP的方式 AJAX 返回信息 处理错误 HTTP 状态码 WrapResult和DontWrapResult特性 Asp.net Mvc 控制器 Asp.net ...

  9. ABP文档 - EntityFramework 集成

    文档目录 本节内容: Nuget 包 DbContext 仓储 默认仓储 自定义仓储 特定的仓储基类 自定义仓储示例 仓储最佳实践 ABP可使用任何ORM框架,它已经内置了EntityFrame(以下 ...

随机推荐

  1. oracle 实例启动报错(ORA-01078: failure in processing system parameters )

    在启动Oracle数据库时报错,如下: [oracle@localhost ~]$ sqlplus / as sysdba SQL*Plus: Release 11.2.0.1.0 Productio ...

  2. 解决MVC模型验证在IE 6 7下不起作用或者报错

    文件版本列出: Jquery版本1.7.1 jQuery Validation 版本1.9.0 (VS2012创建MVC项目自动生成的版本) 最好VS2012创建MVC项目自动生成的版本,而不是VS2 ...

  3. /bin/sh^M: bad interpreter:解决办法

    xcode编译时有时候遇到/bin/sh^M: bad interpreter:没有那个文件或目录这样的错误 可以用以下方式解决 先在控制台cd到报错的目录 vi xxx.sh(报错的那个文件):se ...

  4. java学习笔记 --- 面向对象

    一.对象和类 类(class):类是用于描述现实事物的,它将现实事物进行抽象化,模板化描述.将事物的特点(属性)和行为封装在其中.比如小汽车的图纸,图纸就是小汽车的模版.图纸上画着小汽车的各种特点和功 ...

  5. java学习笔记 --- 条件,循环语句

    一.三元运算符 A:格式    比较表达式?表达式1:表达式2;   B:执行流程:    首先计算比较表达式的值,看是true还是false.    如果是true,表达式1就是结果.    如果是 ...

  6. nodejs 使用mongoose 操作mongodb

    nodejs操作mongodb可以使用mongoose: Mongoose is a MongoDB object modeling tool designed to work in an async ...

  7. OSPF相关知识与实例配置【第一部分】

    OSPF相关知识与实例配置[基本知识及多区域配置] OSPF(开放式最短路径优先协议)是一个基于链路状态的IGP,相比于RIP有无环路:收敛快:扩展性好等优点,也是现在用的最多的:所以这次实验就针对于 ...

  8. Unity 3D Framework Designing(8)——使用ServiceLocator实现对象的注入

    对象的 『注入』 是企业级软件开发经常听到的术语.如果你是一个 Java 程序员,一定对注入有着深刻的映像.不管是SSH框架还是SSM框架,Spring 全家桶永远是绕不过去的弯.通过依赖注入,可以有 ...

  9. oracle查询锁表解锁语句

    --oracle查询锁表解锁语句--首先要用dba权限的用户登录,建议用system,然后直接看sql吧 --1. 如下语句 查询锁定的表: SELECT l.session_id sid, s.se ...

  10. ajax 大洋与小样的第二步

    一.Ajax的对象 XMLHttpRequest的方法 方法 描述 abort() 停止当前请求 getAllResponseHeaders() 把 HTTP请求的所有响应首部作为健/值对返回 get ...