说说ABP项目中的AutoMapper,Castle Windsor(痛并快乐着)

简介:

这篇博客要说的东西跟ABP,AutoMapper和Castle Windsor都有关系,而且也是我在项目中遇到的问题,最终解决了,现在的感受就是“痛并快乐着”。

首先,这篇博客不是讲什么新的知识点,而是一次实战项目的经验总结,其实更是一次弯路或者错误记录吧,方便现在或以后遇到同样问题的人。

下面开始总结。

先来说说我的功能需求:

我要在页面上显示设备所在的城市名称,但是设备实体类中对应的字段是CityId,也就是城市表所对应的Id主键,但是设备实体类所对应的Dto,映射链所对应的属性是City。这里就不贴代码了,你只要记住我要从设备实体类的CityId属性映射到设备Dto类的City属性,这个映射是通过AutoMapper来完成,而且CityId是Int32类型,而City是string类型,因此,映射的过程中肯定是要通过CityId查询出City的名称进而映射到目标属性。通过一张图来表达就是这样的效果:

image

这整个过程都还好理解,问题出在具体的实现代码上了。

因为之前写过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>();
});

原本以为这样就没问题了,结果问题来了:

image

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

public TerminalDeviceResolver() { }

问题又来了:

image

经过调试,我发现这里的_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));
        });
    }
 }
复制代码

问题再次来了,真的是一环套一环啊,这次是编译错误:

image

可见,不能再配置类中通过构造函数进行依赖注入,突然又想到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));
            });
    }
}
复制代码

最终效果如下:

image

顺便看一下响应报文:

image

 

总之,折腾了这么久(痛苦),没白忙活,总算问题解决了,我的心情此时是快乐的!





本文转自tkbSimplest博客园博客,原文链接:http://www.cnblogs.com/farb/p/4981387.html,如需转载请自行联系原作者

目录
相关文章
|
6月前
|
NoSQL Java MongoDB
墙裂推荐!超全SpringBoot2.x的奇技淫巧,满足你一切开发需求
一个小伙伴最近参加某一线互联网公司的面试,被问到了一些Spring Boot源码的问题,看看大家能否答出来:
|
缓存 Java Maven
spring中那些让你爱不释手的代码技巧(续集下)
spring中那些让你爱不释手的代码技巧(续集下)
spring中那些让你爱不释手的代码技巧(续集下)
|
消息中间件 Java 数据库连接
spring中那些让你爱不释手的代码技巧(续集上)
spring中那些让你爱不释手的代码技巧(续集)
spring中那些让你爱不释手的代码技巧(续集上)
|
开发框架 .NET 开发者
浅入AutoMapper
浅入AutoMapper
308 0
|
Java Spring
补习系列(21)-SpringBoot初始化之7招式
背景 在日常开发时,我们常常需要 在SpringBoot 应用启动时执行某一段逻辑,如下面的场景: 获取一些当前环境的配置或变量 向数据库写入一些初始数据 连接某些第三方系统,确认对方可以工作.. 在实现这些功能时,我们可能会遇到一些"坑"。
1519 0
|
Java Spring 安全
第四章:重新来认识你的老朋友Spring框架
欢迎查看Java开发之上帝之眼系列教程,如果您正在为Java后端庞大的体系所困扰,如果您正在为各种繁出不穷的技术和各种框架所迷茫,那么本系列文章将带您窥探Java庞大的体系。本系列教程希望您能站在上帝的角度去观察(了解)Java体系。
29601 0
|
JavaScript Java Android开发
Dagger2让你爱不释手-基础依赖注入框架篇
dagger2的大名我想大家都已经很熟了,它是解决Android或java中依赖注入的一个类库(DI类库)。当我看到一些开源的项目在使用dagger2时,我也有种匆匆欲动的感觉,因此就立马想一探它的究竟,到底能给我带来怎样的好处。
2596 0
|
XML Java 数据格式