Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 在没有构造函数注入的情况下获取服务实例_Angular_Angular2 Di_Angular2 Injection - Fatal编程技术网

Angular 在没有构造函数注入的情况下获取服务实例

Angular 在没有构造函数注入的情况下获取服务实例,angular,angular2-di,angular2-injection,Angular,Angular2 Di,Angular2 Injection,我在bootstrap中定义了一个@Injectable服务。我希望在不使用构造函数注入的情况下获取服务的实例。我尝试使用ReflectiveInjector.resolveAndCreate,但这似乎创建了一个新实例 我尝试这样做的原因是我有一个由许多组件派生的基本组件。现在我需要访问一个服务,但我不想将其添加到ctor中,因为我不想在所有派生组件上注入该服务 TLDR:我需要一个ServiceLocator.GetInstance() 更新:更新了RC5+的代码:是,ReflectiveIn

我在bootstrap中定义了一个
@Injectable
服务。我希望在不使用构造函数注入的情况下获取服务的实例。我尝试使用ReflectiveInjector.resolveAndCreate,但这似乎创建了一个新实例

我尝试这样做的原因是我有一个由许多组件派生的基本组件。现在我需要访问一个服务,但我不想将其添加到ctor中,因为我不想在所有派生组件上注入该服务

TLDR:我需要一个
ServiceLocator.GetInstance()


更新:更新了RC5+的代码:

是,
ReflectiveInjector.resolveAndCreate()
创建一个新的未连接的注入器实例

您可以注入Angulars
Injector
实例,并使用

构造函数(专用注入器:注入器){
获取(MyService);
}

您还可以将
注入器
存储在某个全局变量中,然后使用此注入器实例获取提供的实例,例如,如

中所述。另一种方法包括定义自定义装饰器(一个
CustomInjectable
来设置依赖项注入的元数据:

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);
  }
}
它将利用父构造函数中的元数据,而不是自己的元数据。您可以在子类上使用它:

@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);
  }
}
有关更多详细信息,请参见此问题:


在使用ngModules的更新的角度传感器中,您可以在代码中的任何位置创建可用的变量:

export let AppInjector: Injector;

export class AppModule {
  constructor(private injector: Injector) {
    AppInjector = this.injector;
  }
}
现在,您可以使用
AppInjector
在代码的任何位置查找任何服务

import {AppInjector} from '../app.module';

const myService = AppInjector.get(MyService);
商店服务 组件技术
在多次遇到这个问题后,我设计了一个很好的方法来克服它,通过将getter与Angular
Injector
服务一起使用,而不是直接将服务注入构造函数。这允许在引用之前构造服务时间。我的示例仅使用服务,但同样的事情也可以应用于使用服务的组件,只需将getter放在组件中,而不是示例中的
BService

我所做的是使用getter,使用
Injector
类将服务注入class属性,如果class属性以前没有设置,那么服务只注入一次(第一次调用getter)。这允许服务的使用方式与在构造函数中注入时基本相同,但没有循环引用错误。只需使用getter
This.aService
。只有当您试图在
Bservice
的构造函数中使用
aService
时,这才不会起作用,然后您将拥有same由于
a服务
尚未准备就绪,因此发出循环引用。通过使用getter,您将推迟注入服务,直到您需要它。

有人认为,
AService
依赖于
BService
BService
依赖于
AService
,这是一种不好的形式,但每个规则都有例外,每种情况都不同,所以我认为这是一种简单有效的方法来处理这个问题

//a.service.ts
从“@angular/core”导入{Injectable};
从“/b.service”导入{BService};
@注射的({
providedIn:'根'
})
导出类服务{
建造师(
私人bService:bService,
) { }
公共食物({
log('AService中的foo函数!');
这个.bService.bar();
}
}
//b.service.ts
从“@angular/core”导入{Injectable,Injector};
从“/a.service”导入{AService};
@注射的({
providedIn:'根'
})
导出类BService{
//使用getter“aService”来使用“aService”,而不是这个变量。
私人服务:私人服务;
建造师(
专用注射器:注射器,
) { }
//使用此getter可以使用'AService'而不是_AService变量。
获取aService():aService{
如果(!本服务){
此.\u aService=此.\u injector.get(aService);
}
把这个还给服务部;
}
公共酒吧(){
log('BService中的bar函数!');
this.aService.foo();
}
}

将注入器存储在bootstrap中的全局变量中。然后()听起来像我需要的。问题是没有构造函数,这使得这个答案毫无帮助。如果构造函数在组件中,则是组件注入器,在服务中是模块注入器(如果不是延迟加载的模块,则基本上是根注入器)。您还可以通过添加
@SkipSelf()
来获取父组件注入器。您还可以交互
父组件
getter以获取根注入器。@Rhyous magic?您可以在静态字段或全局变量中共享注入器并从那里访问它,但首先需要在“某处”注入它使用构造函数并将其分配给静态字段。DI容器ng是否使用得那么糟糕,甚至不支持普通DI容器的基本功能?问题是tsc不允许我调用super(参数)因为基本构造函数的参数不匹配。在这种特殊情况下,我们可以从派生类中删除构造函数。这可能也是一个很好的答案。你是国王!哇,我们可以这样做吗?这有一个小问题。你必须为提供服务的延迟加载模块制作单独的注入器。是的,这怎么可能使用需要在构造函数中注入其他服务的服务?
  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);
    }
  }
//call this service directly in component.ts as below:-

 StoreService.getInstance().MyAlertMethod();