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

时间:2017-07-31 11:27:46

标签: 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
}

在构造函数中注入配置是测试的理想选择,并且不需要我读取每个类中的配置和设置。

服务依赖于相同的配置,我想要在我的应用程序中定义一次 - 在启动期间

通过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中,提到&#34;它无法使用接口,因为TypeScript会在运行时编译它们。&#34; 。问题也是+ 2岁,Aurelia和TypeScript都发生了很大变化。无论是否仍然如此,同样的问题也适用于类的实例而不是接口。

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

2 个答案:

答案 0 :(得分:3)

@estus提供的答案是正确的,我已将其标记为答案。虽然,我确实遇到了一些额外的问题,以使其正常工作。为了说明这一点,我已经花时间在下面写了一个答案以及其他详细信息,希望将来能帮助其他人。

1。)使用课程,而不是界面
就像接受的答案状态一样,你不能使用接口 - 它必须是一个类。

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

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

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

3。)将您的课程拆分为不同的文件
这看起来很傻但很重要:类不能在同一个文件中,否则你会收到以下错误:

  

键/值不能为null或未定义。您是否尝试注入/注册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;
}

答案 1 :(得分:1)

无论使用哪种TypeScript版本,运行时都不存在接口。

要同时用作接口和DI令牌,onPaginateChange(event){ alert(JSON.stringify("Current page index: " + event.pageIndex)); } 应该是一个类:

IRemoteServiceConfig