Getting instance of service without constructor in

2019-01-13 10:10发布

I have a @Injectable service defined in bootstrap. I want to get the instance of the service without using constructor injection. I tried using ReflectiveInjector.resolveAndCreate but that seem to create a new instance.

The reason I'm trying to do is I have a base component derived by many components. Now I need to access a service but I don't want to add it to the ctor because I don't want to inject the service on all of the derivative components.

TLDR: I need a ServiceLocator.GetInstance<T>()

UPDATE: Updated code for RC5+: Storing injector instance for use in components

3条回答
Summer. ? 凉城
2楼-- · 2019-01-13 10:20

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:

查看更多
闹够了就滚
3楼-- · 2019-01-13 10:29

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;
  }
}
查看更多
孤傲高冷的网名
4楼-- · 2019-01-13 10:30

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

查看更多
登录 后发表回答