Angular 2 在构造函数之外注入依赖项

问题描述 投票:0回答:2

我目前正在深入研究 Angular 2 中的 DI。我正在使用具体数据类型的通用子类型来实现 REST-Client,如下所示:

class RESTClient<T>{
    constructor() {
        var inj =  ReflectiveInjector.resolveAndCreate([HTTP_PROVIDERS]);
        this.http = inj.get(Http);
        this.conf = RESTConfiguration;
    }
}
class BookClient extends RESTClient<Book>{      
    constructor(){
        // since I dont want to inject the HTTP Providers here, I'm using a custom    injector in the super class
        super();
    }
}

class WriterClient extends RESTClient<Writer>{      
    ...
    ...
}

据我了解,超类 REST-Service 注入的所有 RESTClient 之间将共享一个 http 服务。

现在我想要一个 RESTConfiguration 类:

@Injectable()
export class RESTConfiguration {
    get baseURL() {
     return this._baseURL;
    }

    set baseURL(value) {
        alert("sets value to"+value);
        this._baseURL = value;
    }

    private _baseURL;

}

应在主应用程序中进行如下配置:

initializeApp(){
  this.restconf.baseURL = "http://localhost:3004/";
}
bootstrap(MyApp, [RESTConfiguration]).then();

我现在想知道如何将 RESTConfiguration 的一个单例实例注入 RESTService 类中,而不将其传递给我希望保持无参数的构造函数,以减少代码重复并避免打字稿中的泛型问题。

在上面的示例(第一个代码片段)中,我尝试使用我创建的 ReflectiveInjector 注入我的配置,它为我提供了配置的自定义实例。

我想了几个解决方案:

  1. 通过使用服务或某些静态类属性来访问应用程序“全局注入器”

  2. 在我的配置中实现额外的单例逻辑

  3. 找到一种在构造函数之外使用 Angular-Native 注入方法的方法?

我的想法有错误还是我误用了 DI 框架?

angular typescript dependency-injection singleton
2个回答
36
投票

这应该为这个问题提供一个解决方案,但在任何需要注入服务而不将其作为构造函数参数提供的情况下也有帮助。

我在另一篇文章中看到了这个答案: 存储注入器实例以在组件中使用

您可以在 AppModule 类中配置 Angular Injector,然后在任何其他类中使用它(您可以从任何类访问 AppModule 的成员)。

在AppModule中添加:

export class AppModule { 
  /**
     * Allows for retrieving singletons using `AppModule.injector.get(MyService)`
     * This is good to prevent injecting the service as constructor parameter.
     */
    static injector: Injector;
    constructor(injector: Injector) {
        AppModule.injector = injector;
    }
}

然后在您的其他课程中,您可以执行以下操作(对于此问题,将 MyService 替换为 Http):

@Injectable()
export class MyClass{
    private myService;

    constructor(){
        this.myService = AppModule.injector.get(MyService);
    }
}

这相当于使用:

constructor(private myService: MyService){}

2
投票

从 Angular 14.2 开始,您可以在

注入上下文中使用 
inject()
 中的 
"@angular/core"

从 v14.2 / v15 开始,您可以使用

EnvironmentInjector.runInContext()

 在注入上下文中运行任何代码。从 v16 开始,您可以将 
runInInjectionContext()
 与任何类型的注射器一起使用(
Injector
EnvironmentInjector()
 ...)

比建议的答案好得多。

样品:

import { EnvironmentInjector, inject, runInInjectionContext } from "@angular/core"; class MyService { } class Foo { constructor(private environment: EnvironmentInjector) { runInInjectionContext(environment, () => { const myService = inject(MyService) }) } }
    
© www.soinside.com 2019 - 2024. All rights reserved.