ABP—对象之间的映射

前言

什么是对应之间的映射?

两个实体中只有一个实体指向另一个实体(知道该关系的存在),而另一实体没有指向这个实体(另一实体不知道该关系的存在)

举个很简单的例子:两个对象(类)具有相似或相同的属性,它们之间要互相映射,其实这项工作重复且无聊的工作

比如我们的Person对象 和 一个和它很相似的 TestPersonDto对象

    [Table("Person")]
    public class Person : FullAuditedEntity
    {
        public string Name { get; set; }
        public int Sex { get; set; }
    }
    public class TestPersonDto
    {
        public string Name { get; set; }
         public int Sex { get; set; }
    }

如果我们想把Person的内容映射到TestPersonDto中传统是用以下方法 ,旦是如果数据多起来就是,很复杂的很无聊的操作

 public void TestDto()
        {
           Person entity = _entityRepository.Get(1);
           var personEditDto = new PersonEditDto
           {
              Name = entity.Name,
              Sex = entity.Sex
            };
}

那么今天我们就来看下,我们有什么办法偷懒,简化这些复杂的操作吧。

一.IObjectMapper 接口

我们可以利用IObjectMapper 接口,完成上面的映射操作

        public List<TestPersonDto> TestDto()
        {
            var entity = _entityRepository.GetAllList();
            var peopleList = ObjectMapper.Map<List<TestPersonDto>>(entity);
            return peopleList;
        }

二.AutoMapper的IMapper对象

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

  var peopleList = Mapper.Map<List<TestPersonDto>>(entity);

三.MapTo扩展方法

var peopleList = entity.MapTo<List<TestPersonDto>>();

四.自动映射的特性

我们还存在一个小问题

如果我们:peron------映射到--------》TestpersonDto 是没问题的

如果我们:TestpersonDto------映射到--------》person 是会出错的

        public List<TestPersonDto> TestDto()
        {
            var entity = _entityRepository.GetAllList();
//peron------映射到--------》TestpersonDto 
            var peopleList = entity.MapTo<List<TestPersonDto>>();
//TestpersonDto------映射到--------》person 是会出错的
            var personList = peopleList.MapTo<List<Person>>();
            return peopleList;
        }

为什么:TestpersonDto------映射到--------》person 是会出错的会出错呢?这是因为TestPersonDto实体和Person实体,的列是不匹配的

 

我们有2个解决方案:1.使得2个实体的列一一对应。2.声明映射,告诉系统TestPersonDto实体和Person实体是存在关系的

那么我们怎么告诉系统TestPersonDto实体和Person实体是存在关系呢?

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

我们可以使用AutoMap、AutoMapFrom和AutoMapTo特性来实现实体的关系映射

AutoMap:双向映射

AutoMapFrom与AutoMapTo:单向映射

双向映射,和单向映射的解析:https://blog.csdn.net/lxy15329/article/details/6227168

我们直接在TestPersonDto上声明自动映射的特性([AutoMap(typeof(Person))]),就可以解决这个问题了

    [AutoMap(typeof(Person))]
    public class TestPersonDto
    {
        public int? Id { get; set; }
        public string Name { get; set; }
        public int Sex { get; set; }
    }

 

五.自定义映射 

也行有小伙伴说,我不想用[AutoMapTo(typeof(Person))],的方式声明映射。

那么我们可以用,我们的老办法进行映射,创建一个PersonMapper映射接口,然后一个一个声明实体之间的映射

    internal static class PersonMapper
    {
        public static void CreateMappings(IMapperConfigurationExpression configuration)
        { //创建
            configuration.CreateMap<TestPersonDto, Person>();
            configuration.CreateMap<Person,TestPersonDto>();
        }
    }

最后,不要忘记把这个自定义映射在项目名ApplicationModule中的Initialize()方法声明一下 

 public override void Initialize()
        {
            var thisAssembly = typeof(AbpDemoApplicationModule).GetAssembly();

            IocManager.RegisterAssemblyByConvention(thisAssembly);

            Configuration.Modules.AbpAutoMapper().Configurators.Add(
                // Scan the assembly for classes which inherit from AutoMapper.Profile
                cfg => {
                    cfg.AddProfiles(thisAssembly);
                    PersonMapper.CreateMappings(cfg);
                }
                  
            );
        }

如果这样代码麻烦那么多,还不如使用自动映射的特性好了,别急这个方法并不是用于简单的映射的。是用于自定义映射的

比如我们改动TestPersonDto实体类,给Name改个名改为 MyName。

    //[AutoMap(typeof(Person))]
    public class TestPersonDto
    {
        public int? Id { get; set; }
        public string MyName { get; set; }
        public int Sex { get; set; }
    }

使用自动映射是会出错的,因为系统不会知道,PersonEditDto的 MyName对应的Person的Name

那么,我们就可以用自定义映射苦口婆心得告诉它。

修改一下我们映射接口 

    internal static class PersonMapper
    {
        public static void CreateMappings(IMapperConfigurationExpression configuration)
        { //创建
            configuration.CreateMap<TestPersonDto, Person>().ForMember(a=>a.Name,b=>b.MapFrom(a=>a.MyName));
            configuration.CreateMap<Person, TestPersonDtoo>().ForMember(a=>a.MyName,b=>b.MapFrom(a=>a.Name));
        }
    }

 

我们可以看到是成功的

 

6.关于单元测试中的MapTo

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

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

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

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

参考文章:https://www.cnblogs.com/kid1412/p/6827858.html#intrauction

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值