如何将ABP框架配置中的对象映射功能改写为长尾词?

2026-03-30 10:561阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2040个文字,预计阅读时间需要9分钟。

如何将ABP框架配置中的对象映射功能改写为长尾词?

目录:DTO与实体、实体+DTO、映射烦恼+AutoMapper+集成IObjectMapper/ObjectMapper、对象扩展+DTO与实体、实体是领域驱动设计(Domain Driven Design)中的概念,实体通常一一映射某些对象的具体属性。

目录
  • DTO和实体
    • 实体
    • DTO
  • 麻烦的映射
    • AutoMapper 集成
      • IObjectMapper/ObjectMapper
        • 对象拓展

          如何将ABP框架配置中的对象映射功能改写为长尾词?

          DTO和实体

          实体

          实体是领域驱动设计(Domain Driven Design)中的概念,实体通常一一映射某些对象的固有属性,最常使用的是关系型数据库中的表。

          在 ABP 中,实体位于领域层中,实体类需要实现IEntity<TKey>接口或继承Entity<TKey>基类,示例如下:

          public class Book : Entity<Guid> { public string Name { get; set; } public float Price { get; set; } }

          DTO

          数据传输对象(Data Transfer Object),作为数据传输过程中的数据模型,用于在应用层和表示层之间传输数据。

          在 ABP 中,DTO 位于应用服务层,即本系列文章示例源码中的AbpBase.Application项目。

          通常表示层或其它类型的客户端调用应用服务时,将 DTO 作为参数传递,它使用领域对象(实体)执行某些特定的业务逻辑,并将 DTO (跟传入的 DTO 不是同一个)返回到表示层中,因此表示层与领域层完全隔离。

          DTO 类 可能会跟 实体类的字段/属性高度相似,为每个服务的每个方法创建 DTO 类可能会很枯燥且费时间。

          ABP 的 DTO 类示例如下:

          public class ProductDto : EntityDto<Guid> { public string Name { get; set; } //... }

          麻烦的映射

          前面提到,领域层和应用服务层是要隔离的,例如以下伪代码:

          class HomeController { AddService _service; [HttpPost] public int AddEquip(EquipDto dto) { return _service.Add(dto).Id; } } class AddService { DataContext _context; EquipDto Add(EquipDto dto) { Equip equip = new Equip() { Name = dto.Name; }; _context.Equip.Add(equip); _context.SaveChange(); dto.Id = equip.Id; return dto; } } class EquipDto { int Id; string Name; } ---------- class Equip { int Id; string Name; }

          这样每次都需要手动为 DTO 类和 实体类手动对字段赋值映射,当一个实体有数十个字段时,写出的代码会很冗长,而且容易忽略了某些字段,最终导致了 Bug。

          大家都知道, AutoMapper 正好可以解决这个问题。

          AutoMapper 集成

          ABP 的Volo.Abp.AutoMapper模块封装或集成了 AutoMapper,所以我们正好使用模块,为 ABP 应用定义对象映射。

          关于 AutoMapper 的使用,如何配置 Profile 等,笔者已经单独写到浅入 AutoMapper,请点击链接另外学习 AutoMapper 的使用。

          我们可以在AbpBase.Application项目中,新建 一个AbpBaseApplicationAutoMapperProfile.cs文件,这个文件用于实现 Profile 以及定义映射。将服务领域的映射集中到这个文件中;或者新建一个Profiles文件夹,在其中存放一些 Profile 类。

          其内容如下:

          public class AbpBaseApplicationAutoMapperProfile:Profile { public AbpBaseApplicationAutoMapperProfile() { //base.CreateMap<MyEntity,MyDto>(); } }

          定义完毕后,需要配置 AutoMapper 依赖注入,可在AbpBaseApplicationModuleConfigureServices方法中,增加以下代码:

          Configure<AbpAutoMapperOptions>(options => { // 以模块为单位注册映射 options.AddMaps<AbpBaseApplicationModule>(); //// 以单个 Profiel 为单位注册映射 //options.AddProfile<AbpBaseApplicationAutoMapperProfile>(); });

          在 Debug 阶段,我们担心项目改动代码时,新增的字段忘记了加入到映射配置中,或者其它情况,在 AutoMapper 中,我们可以使用configuration.AssertConfigurationIsValid();来检查映射;在 ABP 中则可使用validate: true参数来开启检查。

          Configure<AbpAutoMapperOptions>(options => { // 以模块为单位注册映射 options.AddMaps<AbpBaseApplicationModule>(validate: true); //// 以单个 Profiel 为单位注册映射 //options.AddProfile<AbpBaseApplicationAutoMapperProfile>(validate: true); });

          IObjectMapper/ObjectMapper

          AbpBase.Application项目中,添加 Nuget 包,搜索Volo.Abp.ObjectMapping并下载相应的稳定版本。

          IObjectMapper 有两个,一个是 AutoMapper 的接口,一个是Volo.Abp.ObjectMapping的 泛型接口。

          AutoMapper 的 IObjectMapper 不好用,所以别用;用Volo.Abp.ObjectMappingIObjectMapper <接口>

          ObjectMapper 是 AutoMapper 中的,我们可以直接在控制器等位置,使用ObjectMapper注入,然后通过 ObjectMapper 实例映射对象。

          ObjectMapper 只有.Map()这个方法用得顺手。

          private readonly ObjectMapper<T1,T2> _mapper; public TestController(ObjectMapper<T1,T2> mapper) { _mapper = mapper; // ... 使用示例 _ = mapper.Map<T1> (); }

          也可以通过依赖注入使用IObjectMapper接口。

          但是因为 ObjectMapper 是泛型类,每种类型的 DTO 都要注入一次的话,会很麻烦,因此这种方案也可以抛弃。

          而 泛型的IObjectMapper<TModule>是一个抽象,我们使用IObjectMapper<TModule>做依赖注入的话,后续如果替换为别的对象映射框架,则不需要修改原有代码即可完成替代。而且IObjectMapper<TModule>比较舒服。

          使用示例:

          private readonly IObjectMapper<AbpBaseApplicationModule> _mapper; public TestController(IObjectMapper<AbpBaseApplicationModule> mapper) { _mapper = mapper; // ... 使用示例 _ = mapper.Map<...>(); }

          对象拓展

          ABP框架提供了实体扩展系统允许你添加额外属性到已存在的对象无需修改相关类。这句话是抄 ABP 官方文档的。

          要支持对象拓展映射,则需要开启配置:

          public class MyProfile : Profile { public MyProfile() { CreateMap<User, UserDto>() .MapExtraProperties(); } }

          时间有限,笔者这里只把官方文档的内容讲清楚,读者看完后,需要继续查阅官方文档,完整了解对象拓展。

          ObjectExtensionManager 是一个拓展对象映射类,可以显式为类拓展一些额外的属性,这个类型在Volo.Abp.ObjectMapping中定义。

          ObjectExtensionManager 是一个类型,但是我们不能直接 new 它,或者使用依赖注入,只能通过ObjectExtensionManager.Instance这个属性获取新的类型。我们无需关心它是用了啥设计模式,还是因为缓存之类的原因这样设计。

          ObjectExtensionManager 有两种属性,其说明如下:

          • AddOrUpdate:是定义对象额外属性或更新对象额外属性的主要方法;
          • AddOrUpdateProperty:快捷地定义单个拓展属性的方法;

          AddOrUpdateProperty用于定义单个属性,AddOrUpdate是一个容器,可以包含多个AddOrUpdateProperty

          AddOrUpdateProperty示例代码如下:

          ObjectExtensionManager.Instance .AddOrUpdateProperty<TestA, string>("Name"); // 为 TestA 类添加了一个 G 属性

          AddOrUpdate的示例代码如下:

          ObjectExtensionManager.Instance .AddOrUpdate<TestA>(options => { options.AddOrUpdateProperty<string>("Name"); options.AddOrUpdateProperty<bool>("Nice"); } );

          当然,我们还可以同时为多个类型同时定义一个额外的属性:

          ObjectExtensionManager.Instance .AddOrUpdateProperty<string>( new[] { typeof(TestA), typeof(TestB), typeof(TestC) }, "Name" );

          如果需要定义多个属性,则可以使用AddOrUpdate

          ObjectExtensionManager.Instance .AddOrUpdate(options => { options.AddOrUpdateProperty<string>("Name"); }, new[]{ typeof(TestA), typeof(TestB) });

          另外它还可以设置默认值、增加验证规则等,这些笔者就不再赘述,读者感兴趣可以点击链接进入官方文档查看。

          docs.abp.io/zh-Hans/abp/latest/Object-Extensions#validation

          到此这篇关于配置ABP框架使用对象映射的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。

          本文共计2040个文字,预计阅读时间需要9分钟。

          如何将ABP框架配置中的对象映射功能改写为长尾词?

          目录:DTO与实体、实体+DTO、映射烦恼+AutoMapper+集成IObjectMapper/ObjectMapper、对象扩展+DTO与实体、实体是领域驱动设计(Domain Driven Design)中的概念,实体通常一一映射某些对象的具体属性。

          目录
          • DTO和实体
            • 实体
            • DTO
          • 麻烦的映射
            • AutoMapper 集成
              • IObjectMapper/ObjectMapper
                • 对象拓展

                  如何将ABP框架配置中的对象映射功能改写为长尾词?

                  DTO和实体

                  实体

                  实体是领域驱动设计(Domain Driven Design)中的概念,实体通常一一映射某些对象的固有属性,最常使用的是关系型数据库中的表。

                  在 ABP 中,实体位于领域层中,实体类需要实现IEntity<TKey>接口或继承Entity<TKey>基类,示例如下:

                  public class Book : Entity<Guid> { public string Name { get; set; } public float Price { get; set; } }

                  DTO

                  数据传输对象(Data Transfer Object),作为数据传输过程中的数据模型,用于在应用层和表示层之间传输数据。

                  在 ABP 中,DTO 位于应用服务层,即本系列文章示例源码中的AbpBase.Application项目。

                  通常表示层或其它类型的客户端调用应用服务时,将 DTO 作为参数传递,它使用领域对象(实体)执行某些特定的业务逻辑,并将 DTO (跟传入的 DTO 不是同一个)返回到表示层中,因此表示层与领域层完全隔离。

                  DTO 类 可能会跟 实体类的字段/属性高度相似,为每个服务的每个方法创建 DTO 类可能会很枯燥且费时间。

                  ABP 的 DTO 类示例如下:

                  public class ProductDto : EntityDto<Guid> { public string Name { get; set; } //... }

                  麻烦的映射

                  前面提到,领域层和应用服务层是要隔离的,例如以下伪代码:

                  class HomeController { AddService _service; [HttpPost] public int AddEquip(EquipDto dto) { return _service.Add(dto).Id; } } class AddService { DataContext _context; EquipDto Add(EquipDto dto) { Equip equip = new Equip() { Name = dto.Name; }; _context.Equip.Add(equip); _context.SaveChange(); dto.Id = equip.Id; return dto; } } class EquipDto { int Id; string Name; } ---------- class Equip { int Id; string Name; }

                  这样每次都需要手动为 DTO 类和 实体类手动对字段赋值映射,当一个实体有数十个字段时,写出的代码会很冗长,而且容易忽略了某些字段,最终导致了 Bug。

                  大家都知道, AutoMapper 正好可以解决这个问题。

                  AutoMapper 集成

                  ABP 的Volo.Abp.AutoMapper模块封装或集成了 AutoMapper,所以我们正好使用模块,为 ABP 应用定义对象映射。

                  关于 AutoMapper 的使用,如何配置 Profile 等,笔者已经单独写到浅入 AutoMapper,请点击链接另外学习 AutoMapper 的使用。

                  我们可以在AbpBase.Application项目中,新建 一个AbpBaseApplicationAutoMapperProfile.cs文件,这个文件用于实现 Profile 以及定义映射。将服务领域的映射集中到这个文件中;或者新建一个Profiles文件夹,在其中存放一些 Profile 类。

                  其内容如下:

                  public class AbpBaseApplicationAutoMapperProfile:Profile { public AbpBaseApplicationAutoMapperProfile() { //base.CreateMap<MyEntity,MyDto>(); } }

                  定义完毕后,需要配置 AutoMapper 依赖注入,可在AbpBaseApplicationModuleConfigureServices方法中,增加以下代码:

                  Configure<AbpAutoMapperOptions>(options => { // 以模块为单位注册映射 options.AddMaps<AbpBaseApplicationModule>(); //// 以单个 Profiel 为单位注册映射 //options.AddProfile<AbpBaseApplicationAutoMapperProfile>(); });

                  在 Debug 阶段,我们担心项目改动代码时,新增的字段忘记了加入到映射配置中,或者其它情况,在 AutoMapper 中,我们可以使用configuration.AssertConfigurationIsValid();来检查映射;在 ABP 中则可使用validate: true参数来开启检查。

                  Configure<AbpAutoMapperOptions>(options => { // 以模块为单位注册映射 options.AddMaps<AbpBaseApplicationModule>(validate: true); //// 以单个 Profiel 为单位注册映射 //options.AddProfile<AbpBaseApplicationAutoMapperProfile>(validate: true); });

                  IObjectMapper/ObjectMapper

                  AbpBase.Application项目中,添加 Nuget 包,搜索Volo.Abp.ObjectMapping并下载相应的稳定版本。

                  IObjectMapper 有两个,一个是 AutoMapper 的接口,一个是Volo.Abp.ObjectMapping的 泛型接口。

                  AutoMapper 的 IObjectMapper 不好用,所以别用;用Volo.Abp.ObjectMappingIObjectMapper <接口>

                  ObjectMapper 是 AutoMapper 中的,我们可以直接在控制器等位置,使用ObjectMapper注入,然后通过 ObjectMapper 实例映射对象。

                  ObjectMapper 只有.Map()这个方法用得顺手。

                  private readonly ObjectMapper<T1,T2> _mapper; public TestController(ObjectMapper<T1,T2> mapper) { _mapper = mapper; // ... 使用示例 _ = mapper.Map<T1> (); }

                  也可以通过依赖注入使用IObjectMapper接口。

                  但是因为 ObjectMapper 是泛型类,每种类型的 DTO 都要注入一次的话,会很麻烦,因此这种方案也可以抛弃。

                  而 泛型的IObjectMapper<TModule>是一个抽象,我们使用IObjectMapper<TModule>做依赖注入的话,后续如果替换为别的对象映射框架,则不需要修改原有代码即可完成替代。而且IObjectMapper<TModule>比较舒服。

                  使用示例:

                  private readonly IObjectMapper<AbpBaseApplicationModule> _mapper; public TestController(IObjectMapper<AbpBaseApplicationModule> mapper) { _mapper = mapper; // ... 使用示例 _ = mapper.Map<...>(); }

                  对象拓展

                  ABP框架提供了实体扩展系统允许你添加额外属性到已存在的对象无需修改相关类。这句话是抄 ABP 官方文档的。

                  要支持对象拓展映射,则需要开启配置:

                  public class MyProfile : Profile { public MyProfile() { CreateMap<User, UserDto>() .MapExtraProperties(); } }

                  时间有限,笔者这里只把官方文档的内容讲清楚,读者看完后,需要继续查阅官方文档,完整了解对象拓展。

                  ObjectExtensionManager 是一个拓展对象映射类,可以显式为类拓展一些额外的属性,这个类型在Volo.Abp.ObjectMapping中定义。

                  ObjectExtensionManager 是一个类型,但是我们不能直接 new 它,或者使用依赖注入,只能通过ObjectExtensionManager.Instance这个属性获取新的类型。我们无需关心它是用了啥设计模式,还是因为缓存之类的原因这样设计。

                  ObjectExtensionManager 有两种属性,其说明如下:

                  • AddOrUpdate:是定义对象额外属性或更新对象额外属性的主要方法;
                  • AddOrUpdateProperty:快捷地定义单个拓展属性的方法;

                  AddOrUpdateProperty用于定义单个属性,AddOrUpdate是一个容器,可以包含多个AddOrUpdateProperty

                  AddOrUpdateProperty示例代码如下:

                  ObjectExtensionManager.Instance .AddOrUpdateProperty<TestA, string>("Name"); // 为 TestA 类添加了一个 G 属性

                  AddOrUpdate的示例代码如下:

                  ObjectExtensionManager.Instance .AddOrUpdate<TestA>(options => { options.AddOrUpdateProperty<string>("Name"); options.AddOrUpdateProperty<bool>("Nice"); } );

                  当然,我们还可以同时为多个类型同时定义一个额外的属性:

                  ObjectExtensionManager.Instance .AddOrUpdateProperty<string>( new[] { typeof(TestA), typeof(TestB), typeof(TestC) }, "Name" );

                  如果需要定义多个属性,则可以使用AddOrUpdate

                  ObjectExtensionManager.Instance .AddOrUpdate(options => { options.AddOrUpdateProperty<string>("Name"); }, new[]{ typeof(TestA), typeof(TestB) });

                  另外它还可以设置默认值、增加验证规则等,这些笔者就不再赘述,读者感兴趣可以点击链接进入官方文档查看。

                  docs.abp.io/zh-Hans/abp/latest/Object-Extensions#validation

                  到此这篇关于配置ABP框架使用对象映射的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。