在 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.container
在 configure()
操作中直接调用默认/全局容器,如下所示:
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 文件中创建了所有类。这似乎根本行不通。
总而言之,完整的应用程序现在看起来像这样并且可以工作:
main.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/