Generic service with multiple values in Angular

yotube
0

Issue

Have multiple services, that provide very similar functionality but with some differences:

  • event-type1, (event-type2 for second service etc.)
  • MODEL_A, (MODEL_B for second service etc.),
  • URL_PART_A, (URL_PART_B for second service etc.),
@Injectable()
export Type1Service extends Socket {
type1Update$ = this.fromEvent<MODEL_A>('event-type1');

constructor() {
super({ url: `${environment.url}/${URL_PART_A}` });
}
}

@Injectable()
export class Type2Service extends Socket {
type2Update$ = this.fromEvent<MODEL_B>('event-type2');

constructor() {
super({ url: `${environment.url}/${URL_PART_B}` });
}
}

@Injectable()
export class Type3Service extends Socket {
type3Update$ = this.fromEvent<MODEL_C>('event-type3');

constructor() {
super({ url: `${environment.url}/${URL_PART_C}` });
}
}

I would like to use generic pattern service by @Inject decorator in components. I tried by export class SocketService<T>, but have the problem with multiple arguments.


Solution

There's no just injecting a generic service directly that returns a different instance based on the generic parameter. So here are a couple of choices - use injection service or create your own service provider. (After writing a custom service provider answer, the injection tokens just seem so much dead simpler that I removed it.)

Using Injection Tokens

/* Service */
export class TypeService<T> extends Socket {
type1Update$ = this.fromEvent<T>(this.eventType);

constructor(urlPart: string, private eventType: string) {
super({ url: `${environment.url}/${urlPart}` });
}
}

/* InjectionTokens - They can live anywhere. */
export const ModelATypeServiceToken = new InjectionToken<TypeService<ModelA>>(
'TypeService for ModelA',
{ factory: () => new TypeService('urlPartA', 'eventType1'), providedIn: 'root' });
export const ModelBTypeServiceToken = new InjectionToken<TypeService<ModelB>>(
'TypeService for ModelB',
{ factory: () => new TypeService('urlPartB', 'eventType2'), providedIn: 'root' });


/* Component */
constructor (@Inject(ModelATypeServiceToken) private typeASvc: TypeService<ModelA>) {}

In the above example, the TypeService is just a simple generic service with urlPart and eventType as a constructor parameters. Injection tokens are created with default factories, that create unique instances of the TypeService per model type.

While it's not a simple as injecting a Generic service directly like you'd do in C#, it's not so bad to define a token per model. How many models do you have in your application that would require engineering something more complex?



Answered By - Daniel Gimenez

Post a Comment

0Comments
Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !
To Top