Getting instance of service without constructor injection

前端 未结 4 1762
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-28 05:21

I have a @Injectable service defined in bootstrap. I want to get the instance of the service without using constructor injection. I tried using Reflective

相关标签:
4条回答
  • 2020-11-28 05:48

    Another approach would consist of defining a custom decorator (a CustomInjectable to set the metadata for dependency injection:

    export function CustomComponent(annotation: any) {
      return function (target: Function) {
    
        // DI configuration
        var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
        var parentAnnotations = Reflect.getMetadata('design:paramtypes', parentTarget);
    
        Reflect.defineMetadata('design:paramtypes', parentAnnotations, target);
    
        // Component annotations / metadata
        var annotations = Reflect.getOwnMetadata('annotations', target);
        annotations = annotations || [];
        annotations.push(annotation);
        Reflect.defineMetadata('annotations', annotations, target);
      }
    }
    

    It will leverage the metadata from the parent constructor instead of its own ones. You can use it on the child class:

    @Injectable()
    export class SomeService {
      constructor(protected http:Http) {
      }
    }
    
    @Component()
    export class BaseComponent {
      constructor(private service:SomeService) {
      }
    }
    
    @CustomComponent({
      (...)
    })
    export class TestComponent extends BaseComponent {
      constructor() {
        super(arguments);
      }
    
      test() {
        console.log('http = '+this.http);
      }
    }
    

    See this question for more details:

    • Angular2 use imported libs from base class
    0 讨论(0)
  • 2020-11-28 05:58

    Yes, ReflectiveInjector.resolveAndCreate() creates a new and unconnected injector instance.

    You can inject Angulars Injector instance and get the desired instance from it using

    constructor(private injector:Injector) {
      injector.get(MyService);
    }
    

    You also can store the Injector in some global variable and than use this injector instance to acquire provided instances for example like explained in https://github.com/angular/angular/issues/4112#issuecomment-153811572

    0 讨论(0)
  • 2020-11-28 06:14

    In the updated Angular where ngModules are used, you can create a variable available anywhere in the code:

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

    Now, you can use the AppInjector to find any service in anywhere of your code.

    import {AppInjector} from '../app.module';
    
    const myService = AppInjector.get(MyService);
    
    0 讨论(0)
  • 2020-11-28 06:15

    StoreService .ts

      import { Injectable} from '@angular/core';
    
        @Injectable()
        export class StoreService {
          static isCreating: boolean = false;
          static instance: StoreService ;
    
          static getInstance() {
            if (StoreService.instance == null) {
              StoreService.isCreating = true;
              StoreService.instance = new StoreService ();
              StoreService.isCreating = false;
            }
            return StoreService.instance;
          }
          constructor() {
            if (!StoreService.isCreating) {
              throw new Error('You can\'t call new in Singleton instances! Call StoreService.getInstance() instead.');
            }
         }
    
      MyAlertMethod(){
        alert('hi);
        }
      }
    

    component.ts

    //call this service directly in component.ts as below:-
    
     StoreService.getInstance().MyAlertMethod();
    
    0 讨论(0)
提交回复
热议问题