【问题标题】:Using Profiles with nestjsx-automapper in nest.js在nest.js 中使用带有nestjsx-automapper 的配置文件
【发布时间】:2020-08-11 03:23:06
【问题描述】:

我正在使用 Chau Tran 的 nestjsx-automapper (https://automapper.netlify.app/docs/usages/init/add-profile)(感谢那段很酷的代码)。我已经按照文档中所示的方式实现了它,并且已经在此处讨论过: How use profiles from nartc/automapper into a nestjs application

但我仍然有一个从我的 Profile 类中访问 AutoMapper 的问题。

这是我的设置:

app.module.ts:

import { Module } from '@nestjs/common';
import { AppService } from './app.service';
import { MerchantModule } from './merchant/merchant.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AutomapperModule, AutoMapper } from 'nestjsx-automapper';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...
    }),
    AutomapperModule.withMapper(),
    MerchantModule
  ],
  providers: [],
  controllers: [],
})
export class AppModule {}

merchant.module.ts:

import { Module } from '@nestjs/common';
import { MerchantController } from './merchant.controller';
import { MerchantService } from './merchant.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Merchant } from './entities/merchant.entity';
import { MerchantProfile } from './profiles/merchant.profile';
import { AutoMapper, AutomapperModule } from 'nestjsx-automapper';

@Module({
  imports: [TypeOrmModule.forFeature([Merchant]), AutomapperModule, MerchantProfile],
  exports: [TypeOrmModule],
  controllers: [MerchantController],
  providers: [MerchantService]
})
export class MerchantModule {}

merchant.profile.ts:

import {
  ProfileBase,
  Profile,
  AutoMapper
} from 'nestjsx-automapper';
import { Merchant } from '../entities/merchant.entity';
import { MerchantDto } from '../dto/merchant.dto';

@Profile()
export class MerchantProfile extends ProfileBase {
  constructor(
    private readonly mapper: AutoMapper) {
    super();
    mapper.createMap(Merchant, MerchantDto);
  }

    configure(): void {      
      return null;
    }
}

merchant.controller.ts:

import { Controller, Get, Param, Post, Body, Put, Delete } from '@nestjs/common';
import { MerchantService } from './merchant.service';
import { Merchant } from './entities/merchant.entity';
import { MerchantDto } from './dto/merchant.dto';
import { DeleteResult } from 'typeorm';
import { AutoMapper, InjectMapper } from 'nestjsx-automapper';

@Controller('merchant')
export class MerchantController {

    constructor(
        private merchantService: MerchantService,
        @InjectMapper() private readonly mapper: AutoMapper) { }

    @Get()
    public async findAll(): Promise<MerchantDto[]> {
        return this.mapper.mapArray(await this.merchantService.find(),MerchantDto);
    }
}

当我使用此设置运行应用程序时,出现以下异常: Nest 无法解析 AutomapperModule (?) 的依赖关系。请确保索引 [0] 处的参数 AutomapperExplorer 在 AutomapperModule 上下文中可用。

【问题讨论】:

    标签: node.js mapping automapper nestjs


    【解决方案1】:

    AppModule 中的AutoMapperModule.withMapper() 是您唯一需要使用AutoMapperModule 的时间。

    withMapper() 创建一个 AutoMapper 单例,当您想在 Service(或任何 Injectable)中使用 Mapper 时,可以通过 @InjectMapper() 使用该单例。

    至于Profile,正确的语法如下:

    @Profile()
    export class MerchantProfile extends ProfileBase {
      constructor(mapper: AutoMapper) { // no private readonly.
        super();
        mapper.createMap(Merchant, MerchantDto);
      }
      // no configure() method
    }
    

    以下是@nartc/automapper源代码addProfile()的写法:

    addProfile(profile: new (mapper: AutoMapper) => MappingProfile): AutoMapper {
        this._profileStorage.add(this, new profile(this));
        return this;
    }
    

    您可以在内部看到,@nartc/automapper 将实例化 (new profile()) 并将 AutoMapper 实例传递给 Profile 的构造函数,以便您可以在 Profile's constructor 中使用它

    对于你MerchantModule中的这段代码

    import { Module } from '@nestjs/common';
    import { MerchantController } from './merchant.controller';
    import { MerchantService } from './merchant.service';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { Merchant } from './entities/merchant.entity';
    // import { MerchantProfile } from './profiles/merchant.profile';
    // this is all you need which is to import the profile so TypeScript can execute it. Don't need `MerchantProfile` at all
    import './profiles/merchant.profile';
    import { AutoMapper, AutomapperModule } from 'nestjsx-automapper';
    
    @Module({
      imports: [TypeOrmModule.forFeature([Merchant])], // don't need to import AutoMapperModule again. MerchantProfile is not a Module so you can't import it
      exports: [TypeOrmModule],
      controllers: [MerchantController],
      providers: [MerchantService]
    })
    export class MerchantModule {}
    

    在你的MerchantController:

    @Controller('merchant')
    export class MerchantController {
    
        constructor(
            private merchantService: MerchantService,
            @InjectMapper() private readonly mapper: AutoMapper) { }
    
        @Get()
        public async findAll(): Promise<MerchantDto[]> {
            // make sure `this.merchantService.find()` returns an Array of 
            // Merchant instances. If not, please provide an extra param to map()
            // return this.mapper.mapArray(await this.merchantService.find(),MerchantDto);
            return this.mapper.mapArray(await this.merchantService.find(), MerchantDto, Merchant); // notice the 3rd parameter is the Source model.
        }
    }
    

    如果这对您有用,请告诉我。如果没有,请在nestjsx-automapper repo 中创建问题并提供可重现的存储库,我会尽快查看。

    【讨论】:

    • 谢谢周!我会通过它,让你知道。另一个问题:我应该如何处理一个实体的不同 DTO?例如。我需要在创建它时将没有“ID”属性的实体传递给 ORM,但我需要在更新时拥有 ID 属性?或者 GET 请求的 DTO 将再次成为另一个。我已经看到了具有不同 DTO 类的解决方案(例如 create-merchant.dto、update-merchant.dto),但我认为这是一堆样板文件和代码重复。你有什么提示吗?
    • 你的例子很有效。也许可以在automapper.netlify.app/docs/nest 上的文档中添加一个带有nest.js 实现的示例Projekt?
    • @MichaelFürst 假设您有 MerchantDto 并且使用 MerchantDto 进行创建和更新。唯一的区别是 Id 可以为空。在这种情况下你可以做的是有一个 reverseMap()
    • Mapper.createMap(Merchant, MerchantDto).reverseMap().forPath(s => s.id, mapDefer(dest => dest.id ? mapFrom(d => d.id): 忽略()))
    • 如果您想详细讨论,请在 Discord 上与我联系
    【解决方案2】:

    我不太熟悉 AutoMappModule 的工作原理,但它看起来像在您的 MerchantModule 中您导入 AutoMapperModule 而您应该导入 AutoMapperModule.withMapper(),类似于你在AppModule 中做了。

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多