Let's assume I have a two modules which are exporting BService
and CService
where both of those services extends AService
So code looks like this:
abstract class AService {
public run() {}
}
@Injectable()
export class BService extends AService {}
@Injectable()
export class CService extends AService {}
@Module({
providers: [BService],
exports: [BService],
})
export class BModule {}
@Module({
providers: [CService],
exports: [CService],
})
export class CModule {}
@Injectable()
class AppService {
constructor(protected readonly service: AService) {}
public run(context: string) { // let's assume context may be B or C
this.service.run();
}
}
@Module({
imports: [CModule, BModule],
providers: [{
provide: AppService,
useFactory: () => {
return new AppService(); // how to use BService/CService depending on the context?
}
}]
})
export class AppModule {}
But the key is, I cannot use REQUEST
(to inject it directly in useFactory
) from @nestjs/core
as I'm using this service in cron jobs and with the API call
I also don't think Factory
pattern is useful there, I mean it would work but I want to do it correctly
I was thinking about property based injection.
But I'm not sure how to use it in my case
In my opinion, the factory approach is exactly what you need. You described that you need a different service based on the context which is a great for for the factory approach. Let's try this:
Create an injectable factory:
import { Injectable } from '@nestjs/common';
import { AService } from './AService';
import { BService } from './BService';
import { CService } from './CService';
@Injectable()
export class ServiceFactory {
public getService(context: string) : AService {
switch(context) {
case 'a': return new BService();
case 'b': return new CService();
default: throw new Error(`No service defined for the context: "${context}"`);
}
}
}
Now import that factory into your app module:
import { ServiceFactory } from './ServiceFactory';
import { AService } from './AService';
@Module({
providers: [AppService, ServiceFactory]
})
export class AppModule {}
Now your app service will get the factory as a dependency which will create the appropriate service based on the context:
import { ServiceFactory } from './ServiceFactory';
import { AService } from './AService';
@Injectable()
class AppService {
constructor(readonly serviceFactory: ServiceFactory) { }
public run(context: string) {
const service: AService = this.serviceFactory.getService(context);
service.run();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With