Reputation: 678
If I have an Angular Module A
that depends on a certain service S
. But instead of implementing the service directly, I want to deal with an interface I
and let the consumer of A
pass the actual implementation when importing it. The implementation will be an Angular service decorated with @Injectable and has its own dependencies.
Is that feasible in Angular? if yes, what are the steps to implement it?
Upvotes: 3
Views: 848
Reputation: 28434
To archive this, you could use abstract classes
instead of interfaces
to make the implementations exchangeable:
app/
├── foo.service.ts
├── foo/
│ ├── abstract-foo.provider.ts
│ ├── foo.module.ts
│ ├── foo.component.ts
├── app.module.ts
Now the following files:
// foo.service.ts
@Injectable()
export class FooService extends AbstractFooProvider {
ctor(private _fooDependency: SomeOtherFooService){}
foo(): boolean {
return this._fooDependency.isFoo();
}
}
// foo.module.ts
@NgModule({
declarations: [FooComponent],
exports: [FooComponent]
})
export class FooModule {
static withConfiguration(implementationProvider: Provider): ModuleWithProviders {
return {
ngModule: FooModule,
providers: [implementationProvider]
};
}
}
// abstract-foo.provider.ts
export abstract class AbstractFooProvider {
foo(): boolean;
}
// foo.component.ts
@Component({})
export class FooComponent {
ctor(private _fooProvider: AbstractFooProvider){}
}
// app.module.ts
export const FOO_PROVIDER : ClassProvider = {
provide: AbstractFooProvider,
useClass: FooService
};
@NgModule({
imports: [
FooModule.withConfiguration(FOO_PROVIDER)
]
})
export class AppModule {}
Upvotes: 6
Reputation: 18281
You can use an InjectionToken
:
export let SERVICE_A = new InjectionToken<MyService>('service.a');
Here, I've created an injection token for the interface MyService
.
In my module, I match that token to a given implementation:
{ provide: SERVICE_A, useClass: ServiceImplA },
Then, in my component I specify which token to use:
constructor(@Inject(SERVICE_A) private service: MyService) { }
You can, of course, create a different token for each implementation.
Here is an example in StackBlitz. To see it in action, you can change the token from SERVICE_A
to SERVICE_B
https://stackblitz.com/edit/angular-nwglpj?file=app%2Fhello.component.ts0
Upvotes: -1