typescript - 定义全局 TypeScript 配置(接口(interface)),用于 Aurelia 依赖注入(inject)

标签 typescript dependency-injection aurelia

在 Aurelia 中,我有几个依赖于相同配置的类。使用 IoC/DI,这个配置可以作为构造函数参数提供,这似乎很自然。例如:

@autoinject
export class CustomerService {
    constructor(config: IRemoteServiceConfig) {
    }
}

@autoinject
export class GummyBearService {
    constructor(config: IRemoteServiceConfig) {
    }
}

在最简单的示例中,IRemoteServiceConfig 可能看起来像这样(为了简洁,删除了其他内容):

export IRemoteServiceConfig {
    endpoint: string;
    apiKey?: string;
    // etc. several other settings
}

将配置注入(inject)构造函数非常适合测试,并且不需要我读取每个类中的配置和设置。

这些服务依赖于相同的配置,我希望在启动期间在我的应用程序中定义一次

通读 Aurelia docs on dependency injection ,我看到有几种方法可用于此目的,例如 registerInstance()registerResolver()registerSingleton()。这些文档确实缺乏一些关于如何在哪里来定义它的上下文。

我在启动例程的 configure() 部分中开始执行如下操作:

// register a static config; for brevity these are hardcoded settings
// but could come from anywhere
container.registerSingleton(IRemoteServiceConfig, () => {
    return <IRemoteServiceConfig> {
        endpoint: 'http://foo.com/api/v23/',
        apiKey: 'abc'
    }
});

它似乎没有拾取任何东西(没有错误)。但这也可能只是我对如何初始化容器的无知。

我的问题:如何以及在哪里可以在 Aurelia 中定义 IRemoteServiceConfig(如果有的话),以便一旦 DI 启动服务,它就会自动获取我的(硬编码的)配置?

请注意,在 this SO question 中有人提到“它无法与接口(interface)一起使用,因为 TypeScript 在运行时将这些接口(interface)编译掉。”。这个问题也已经过去了 2 年了,在 Aurelia 和 TypeScript 中都发生了很多变化。不管情况是否仍然如此,同样的问题也适用于类的实例而不是接口(interface)。

另请注意,我知道诸如 aurelia-configuration 之类的库,它似乎适合将应用程序设置存储在配置文件中(并且工作得很好)。这对于给出的例子来说更有意义。但问题纯粹与如何定义由 Aurelia DI 解析的接口(interface)或类的特定实例有关。

最佳答案

@estus 提供的答案是正确的,我已将其标记为答案。尽管如此,我确实遇到了一些其他问题才能使其正常工作。为了指出这一点,我花时间写了一个答案,并在下面提供了更多详细信息,希望它可以帮助将来的其他人。

1.) 使用类,而不是接口(interface)
就像接受的答案状态一样,您不能使用接口(interface) - 它必须是一个类。

2.) 通过aurelia.container访问全局容器实例
该文档没有提到如何获取容器的实例。但是您可以通过 aurelia.containerconfigure() 操作中直接调用默认/全局容器,如下所示:

aurelia.container.registerSingleton(RemoteServiceConfig, () => {
  var config = new RemoteServiceConfig();
    config.endpoint = 'http://foo.com/api/v23/',
    config.apiKey = 'abc'
});

我在初始化 Container() 的新实例时犯了错误,并且还尝试在 configure() 操作中以某种方式注入(inject)它。我不应该:)

3.) 将类拆分到不同的文件中
这看起来很愚蠢,但很重要:这些类不能位于同一个文件中,否则您将收到以下错误:

key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?

出于原始问题的目的,我在同一个 app.ts 文件中创建了所有类。这似乎根本行不通。

总而言之,完整的应用程序现在看起来像这样并且可以工作:

ma​​in.ts

import { Aurelia } from 'aurelia-framework'
import { RemoteServiceConfig } from './app';

export function configure(aurelia: Aurelia) {
  aurelia.use
    .standardConfiguration()
    .feature('resources');

  aurelia.container.registerSingleton(RemoteServiceConfig, () => {
    var config = new RemoteServiceConfig();
      config.endpoint = 'http://foo.com/api/v23/',
      config.apiKey = 'abc'
  });

  aurelia.start().then(() => aurelia.setRoot());
}

app.ts

import { autoinject } from 'aurelia-dependency-injection';

// note: classes below should be 3 different files!

@autoinject
export class App {
  constructor(private service: CustomerService) {
  }
}

@autoinject
export class CustomerService {
  constructor(private config: RemoteServiceConfig) {
  }
}

export class RemoteServiceConfig {
  public endpoint: string;
  public apiKey?: string;
}

关于typescript - 定义全局 TypeScript 配置(接口(interface)),用于 Aurelia 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45414696/

相关文章:

java - Mockito 与 JMockit 以及依赖注入(inject)

ios - 台风与单例 AppDelegate

aurelia - View 模型是单例吗?或不?

aurelia - 如何更改 Aurelia 项目的默认端口

scala - Scala 有没有办法隐式转换隐式参数?

javascript - 提高 Aurelia 框架在移动设备上的性能

javascript - 如何为 ngrx/store 2.2.1 配置 system-config.js

typescript - 如何使用 gulp-changed 和 gulp-typescript

Angular 2 : dynamic selector property

javascript - DraftJs:使用实体键替换实体