简体   繁体   中英

How to get generic service using wrapper's class generic type?

I'm using angular 5 and I'm trying to lower the amount of parameters are injected in my classes. I'm not looking to discuss if service locator is an anti-pattern or not, just understand if angular/typescript would allow me to do that, please.

I use service locator for that quite often, but there's one case I can't figure out how to solve and the few questions I read about generic injection did not help much :/

Here's my case:

export abstract class BaseComponent<T extends BaseModel> {
    protected recordId?: number = undefined;
    protected alertService: AlertService;
    protected translateService: TranslateService;
    protected router: Router;

    protected constructor(
        protected activatedRoute: ActivatedRoute,
        protected store: BaseCrudStore<T>,
        protected baseType: { new(): T; }
    ) {
        this.record = new baseType();
        this.alertService = ServiceLocator.injector.get(AlertService);
        this.translateService = ServiceLocator.injector.get(TranslateService);
        this.router = ServiceLocator.injector.get(Router);
        //...
   }
}

I'd like BaseCrudStore to also be resolved using service locator instead of injecting it through the constructor. Is there a way to accomplish this? Is there a way to get my store using the service locator? As you can see, the BaseCrudStore is also generic and the generic parameter is the same one of the BaseComponent class.

So far I can't also fix injecting ActivatedRoute . It does inject, but (very likely) because of angular's structure it does not represent the current route, which makes sense thinking how it is built. If you know how to also fix this :)

I appreciate any help on this... my code is working 100%, it's just something that's been bothering me for a few months and I couldn't fix it.

ServiceLocator init:

export class AppModule {
    constructor(private injector: Injector) {
        ServiceLocator.injector = this.injector;
    }
}

Thanks!

If you already have an injector in your environment, you can try something like this:

protected store: Store<T>;

protected constructor() {
    this.store = AppInjectorService.injector.get<Store<T>>(Store);
}

Tested on Angular 6.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM