从 Aurelia 依赖注入容器显式请求新实例

Explicitly request new instances from Aurelia dependency injection container

在 Aurelia (+ TypeScript) 中...

有没有办法在上下文中(例如在视图模型中)直接引用容器并从中显式 "request" 个新实例?

要在您的 view-model 中获取容器,您 通常 有 3 个选项:

1。注入容器

@inject(Container) 装饰你的视图模型或者简单地应用 any 装饰器(这使得 tsc 发出类型元数据)并确保在你的构造函数中指定类型,如下所示:

constructor(private container: Container) {}

这是获取容器的推荐方法,因为它会给你 child 容器范围内的特定视图模型。这意味着,如果您请求 ElementRouter 之类的内容,您还将获得范围限于该视图模型的内容。

您注册到该容器的内容只能通过该容器或其 children 解析 - 而不是其兄弟或 parents.

2。使用全局容器

总有一个 "root" 容器,您可以通过 Container.instance 静态 属性.

在代码中的任何位置访问它

这对于某些在正常 aurelia 生命周期之外存在的组件很有用,或者如果您确实需要 root。你会想尽可能避免这种情况,因为它会导致意大利面条代码。

3。 "Abuse"路由器

我不一定会推荐这个,但每个配置的路由器上总是有一个 .container 属性。这是作用域 child 路由器 - 如果将它注入到视图模型的构造函数中,就会得到相同的路由器。

引用容器后:

调用 container.get(Foo),仅从该容器中获取 Foo 的实例,或调用 container.getAll(Foo) 从该容器中获取所有 Foo 的列表及其所有 parents,直到根。

  • 对于构造函数,它默认调用构造函数并递归解析其依赖项(如果有)。然后它将实例存储为 单例.

  • 对于任何不是构造函数的东西(nullundefined 除外),它默认存储值并在您再次使用相同的值调用它时返回它(不是特别有用但至少没有错误)。

  • 对于nullundefined会报错

生命周期和范围

有两种终身注册类型:

  • singleton 在容器的生命周期内给出相同的实例
  • transient 每次调用容器时都会提供一个新实例

singleton 的生命周期进一步取决于它注册到的容器的生命周期,在典型的 child 容器的情况下,是视图模型的生命周期。

API表面的其他部分本质上只是singletontransient的differently-scoped变体。

设置注册类型

这里有很多选项,我不会在这里一一介绍。与您相关的是直接容器 API:

container.register...(key, fn)

之后,当你调用container.get(key)时,它会根据你刚刚设置的注册来解析依赖关系。您也可以事后更改它 - 只会覆盖现有的解析器。

  • 单例:container.registerSingleton(Foo)

  • 实例(单例但你提供实例):container.registerInstance(Foo, new Foo(new Bar()))

  • 瞬态:container.registerTransient(Foo)

  • 自定义函数:container.registerHandler(Foo, (container, key, resolver) => new Foo(container.get(Bar))(对于具有单例 Bar 的瞬态 Foo

还有其他选项,但这些是最常用的选项。

关于 key, fn 参数的最后说明:调用 register(Foo) 等同于调用 register(Foo, Foo)。你也可以说 register("foo", Foo) 如果你没有 want/don 从你想调用它的地方没有对 class 名称的引用。

能够打开调试器并说 document.body.aurelia.container.get("foo") 是我个人认为有时调试非常方便的东西:)