说说ABP项目中的AutoMapper,Castle Windsor(痛并快乐着)
这篇博客要说的东西跟ABP,AutoMapper和Castle Windsor都有关系,而且也是我在项目中遇到的问题,最终解决了,现在的感受就是“痛并快乐着”。
首先,这篇博客不是讲什么新的知识点,而是一次实战项目的经验总结,其实更是一次弯路或者错误记录吧,方便现在或以后遇到同样问题的人。
下面开始总结。
先来说说我的功能需求:
我要在页面上显示设备所在的城市名称,但是设备实体类中对应的字段是CityId,也就是城市表所对应的Id主键,但是设备实体类所对应的Dto,映射链所对应的属性是City。这里就不贴代码了,你只要记住我要从设备实体类的CityId属性映射到设备Dto类的City属性,这个映射是通过AutoMapper来完成,而且CityId是Int32类型,而City是string类型,因此,映射的过程中肯定是要通过CityId查询出City的名称进而映射到目标属性。通过一张图来表达就是这样的效果:

这整个过程都还好理解,问题出在具体的实现代码上了。
因为之前写过AutoMapper的系列教程(如果您还不知道什么是AutoMapper,请点击这里),所以我想到了使用自定义值解析器,所以自己写了个类:
/// <summary>
///
/// 自定义值解析器,目的在于将TerminalDevices的CityId映射成具体的string类型的城市名称
/// </summary>
public class TerminalDeviceResolver : ValueResolver<TerminalDevices, string>
{
private readonly ICityAppService _cityAppService ; public TerminalDeviceResolver(ICityAppService cityAppService)
{
_cityAppService = cityAppService;
} protected override string ResolveCore(TerminalDevices source)
{
if (source.CityID.HasValue)
{
var cityId = Convert.ToInt32(source.CityID);
var city=_cityAppService.GetCity(new CityInput() { Id = cityId });
if (city!=null)
{
return city.Name;
}
return "找不到该城市";
}
return "CityID为空";
}
}
然后再在配置类中修改一下配置:
Mapper.CreateMap<TerminalDevices, TerminalDeviceOutput>().ForMember(output => output.City, opt =>
{
opt.ResolveUsing<TerminalDeviceResolver>();
});
原本以为这样就没问题了,结果问题来了:

这里报错说“类型需要有一个具有0个参数或者只有可选参数的构造函数”。我猜想肯定是说自定义解析器类,于是又定义了个无参的构造函数。
public TerminalDeviceResolver() { }
问题又来了:

经过调试,我发现这里的_cityAppService为null,那我就纳闷了,我上面不是已经通过构造函数注入了该服务接口对象了嘛,怎么会是null呢?仔细调试发现,程序走的是无参的构造函数,没有走这个依赖注入的构造函数,怪不得为null呢?
找到原因之后,我就又思考了,如何通过构造函数注入依赖呢?我又想到了AutoMapper中自定义解析器的ConstructedBy方法,接下来我又这样修改了一下映射配置类:
public class TerminalDeviceProfile:Profile
{
private readonly ICityAppService _cityAppService ;
public TerminalDeviceProfile(ICityAppService cityAppService)
{
_cityAppService = cityAppService;
}
protected override void Configure()
{
Mapper.CreateMap<TerminalDevices, TerminalDeviceDto>();
Mapper.CreateMap<TerminalDevices, TerminalDeviceOutput>().ForMember(output => output.City, opt =>
{
opt.ResolveUsing<TerminalDeviceResolver>().ConstructedBy(() => new TerminalDeviceResolver(_cityAppService));
});
}
}
问题再次来了,真的是一环套一环啊,这次是编译错误:

可见,不能再配置类中通过构造函数进行依赖注入,突然又想到ABP中可以这样做,直接解析:
var cityAppService = IocManager.Instance.Resolve<ICityAppService>();
因此,最终代码是这样的:
public class TerminalDeviceProfile : Profile
{ protected override void Configure()
{
var cityAppService = IocManager.Instance.Resolve<ICityAppService>();
Mapper.CreateMap<TerminalDevices, TerminalDeviceDto>();
Mapper.CreateMap<TerminalDevices, TerminalDeviceOutput>()
.ForMember(output => output.City, opt =>
{
opt.ResolveUsing<TerminalDeviceResolver>()
.ConstructedBy(() => new TerminalDeviceResolver(cityAppService));
});
}
}
最终效果如下:

顺便看一下响应报文:

总之,折腾了这么久(痛苦),没白忙活,总算问题解决了,我的心情此时是快乐的!
说说ABP项目中的AutoMapper,Castle Windsor(痛并快乐着)的更多相关文章
- AutoMapper之ABP项目中的使用介绍
最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMapper只要用来数据转换,在园里已经有很多 ...
- ABP项目中的使用AutoMapper
AutoMapper之ABP项目中的使用 最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMa ...
- 在 ASP.NET Core 项目中使用 AutoMapper 进行实体映射
一.前言 在实际项目开发过程中,我们使用到的各种 ORM 组件都可以很便捷的将我们获取到的数据绑定到对应的 List<T> 集合中,因为我们最终想要在页面上展示的数据与数据库实体类之间可能 ...
- ABP项目中使用Swagger生成动态WebAPI
本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...
- 在基于AngularJs架构的ABP项目中使用UEditor
[前提须知] 读过此篇博客 了解angular-ueditor 了解ABP如何使用 会使用VS2017 [1.下载ABP模板] https://aspnetboilerplate.com/Templa ...
- Abp项目中的领域模型实体类访问仓储的方法
首先声明,不推荐使用这种方法.实体访问仓储是不被推荐的! 1.简单粗暴的方法 Abp.Dependency.IocManager.Instance.Resolve>(); 2.绕个弯子的方法 首 ...
- abp项目中无法使用HttpContext.Current.Session[""]的问题
web项目Global.asax.cs中加入如下代码 public override void Init() { this.PostAuthenticateRequest += (sender, e) ...
- ABP项目概述
在系统性介绍整个ABP框架之前,我们首先需要对ABP框架有一个大概的了解,ABP框架的全称是:Asp.Net Boilerplate Project(即Asp.Net 的样板项目)顾名思义就是能够通过 ...
- Castle Windsor常用介绍以及其在ABP项目的应用介绍
最近在研究ABP项目,有关ABP的介绍请看阳光铭睿 博客,ABP的DI和AOP框架用的是Castle Windsor下面就对Castle Windsor项目常用方法介绍和关于ABP的使用总结 1.下载 ...
随机推荐
- 【转载】C++ IO库
本篇随笔为转载,原贴地址:<C++ Primer>第8章 IO库 学习笔记. 1.IO类 #include <iostream> istream//从流中读取数据 ostrea ...
- 在数学建模中学MATLAB
为期三周的数学建模国赛培训昨天正式结束了,还是有一定的收获的,尤其是在MATLAB的使用上. 1. 一些MATLAB的基础性东西: 元胞数组的使用:http://blog.csdn.net/z1137 ...
- 学习打造自己的DEBUG_NEW
学习范例http://www.cppblog.com/Robertxiao/archive/2012/11/05/194547.html 在使用MFC库开发程序时,我非常喜欢MFC框架中的内存泄漏诊断 ...
- centos dns配置
vi /etc/sysconfig/network-scripts/ifcfg-[tab两下] 新增以下修改 ONBOOT=yes #开启自动启用网络连接 IPADDR0=192.168.21.12 ...
- eclipse使用技巧、快捷键
1.alt+/ 自动提示符,可以快速补整,提高效率. 输入Sysout,再按下alt+/,就可以打印了. 输入main,再按下alt+/,可以直接显示main方法. 2.ctrl+左键,快速进入 ...
- 5.HotSpot的算法实现
1.枚举根节点 在可达性分析中,可以作为GC Roots的节点有很多,但是现在很多应用仅仅方法区就有上百MB,如果逐个检查的话,效率就会变得不可接受. 而且,可达性分析必须在一个一致性的快照中进行-即 ...
- UVA 11624 Fire!(广度优先搜索)
题目大意:在一个N*M的迷宫内,J代表某人(只有一个),F代表火(可能不只一个),#代表墙,火每分钟会向四周除了墙以外的地方扩散一层,问人能否在没被火烧到 之前逃出迷宫,若能逃出输出最短时间.很明显的 ...
- BIEE 11g 安装
1.安装oracle 创建字符集为AL32UTF8的实力MERIT sys密码merit 创建biee用户 create tablespace biee datafile 'D:\ORADATA\M ...
- 使用 BeanCopier 复制对象
Cglib是一款比较底层的操作java字节码的框架. BeanCopier是一个工具类,可以用于Bean对象内容的复制. 复制Bean对象内容的方法有很多,比如自己手动get set ,或者使用Pro ...
- jzoj[1438]NOIP2013火柴排队
读题: 相邻两个火柴可以交换?两个火柴序列?嗅到了归并排序的味道. 读完题目之后,我们可以知道,如果想要交换次数最少,可以先固定一个序列不变,比如说a序列不变,变b序列 样例是 4 2 3 1 4 3 ...