文档目录

本节内容:

简介

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

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. ICC_lab总结——ICC_lab2:设计规划

    PS:字丑,禁止转载!!! 首先先写出大概的流程,然后是一些教材的理论知识总结,最后是进行lab2的一些流程概述. 教材的理论知识总结主要是:数字集成电路物理设计学习总结--布图规划和布局 --> ...

  2. Windows Phone 8.1开发:触控和指针事件2

    原文出自:http://www.bcmeng.com/windows-phone-touch1/ 请在此输入内容(想死啊,写了一个小时,直接没保存不小心删掉了.那就简单说说吧)Pointer事件有以下 ...

  3. 如何用正确的姿势查看 主机系统的CPU信息

    一.关于CPU的几个概念 CPU的作用 计算机中的中央处理单元(CPU)执行基本的计算工作 -- 运行程序.但是,一个单核的CPU同一时间只能一次执行一个任务,为了提高计算机的处理能力,也就出现了多C ...

  4. java学习笔记 --- String类

    一.定义 就是由多个字符组成的一串数据.也可以看成是一个字符数组. 注意: 1.字符串是常量:它们的值在创建之后不能更改.为什么? 意思就是说字符串确定了,就会在常量池中生成这个字符串. 所以说它的值 ...

  5. (转)经验分享:CSS浮动(float,clear)通俗讲解

    很早以前就接触过CSS,但对于浮动始终非常迷惑,可能是自身理解能力差,也可能是没能遇到一篇通俗的教程. 前些天小菜终于搞懂了浮动的基本原理,迫不及待的分享给大家. 写在前面的话: 由于CSS内容比较多 ...

  6. window7使用svn(svn系列 客户端 知识二总结)

     ♣eclipse插件subclipse  ♣TortoiseSVN  ♣svn操作  ♣注意事项 使用svn可以在eclipse直接装subclipse或者在windows使用TortoiseSVN ...

  7. 老李分享:Mac快捷键

    poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...

  8. 用pl/sql游标实现约瑟夫环

    什么是约瑟夫环: 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为1的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数, ...

  9. Mybatis基础学习(四)—关系映射

    一.模型分析 user和orders user---->orders 一个用户可以创建多个订单,一对多. orders--->user 一个订单只由一个用户创建,一对一.   orders ...

  10. Oracle数据库报错:索引中丢失 IN 或 OUT 参数

    另外,我记得好像以前也有这样的错误发生,当时的错误原因是,参数类型和数据库的类型不匹配引起的. 所以,如果有这种错误发生,应该仔细检查每个字段赋值的地方,检查类型及非空. 也可能是传参数问题,传参数过 ...