从 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 容器范围内的特定视图模型。这意味着,如果您请求 Element
或 Router
之类的内容,您还将获得范围限于该视图模型的内容。
您注册到该容器的内容只能通过该容器或其 children 解析 - 而不是其兄弟或 parents.
2。使用全局容器
总有一个 "root" 容器,您可以通过 Container.instance
静态 属性.
在代码中的任何位置访问它
这对于某些在正常 aurelia 生命周期之外存在的组件很有用,或者如果您确实需要 root。你会想尽可能避免这种情况,因为它会导致意大利面条代码。
3。 "Abuse"路由器
我不一定会推荐这个,但每个配置的路由器上总是有一个 .container
属性。这是作用域 child 路由器 - 如果将它注入到视图模型的构造函数中,就会得到相同的路由器。
引用容器后:
调用 container.get(Foo)
,仅从该容器中获取 Foo
的实例,或调用 container.getAll(Foo)
从该容器中获取所有 Foo
的列表及其所有 parents,直到根。
对于构造函数,它默认调用构造函数并递归解析其依赖项(如果有)。然后它将实例存储为 单例.
对于任何不是构造函数的东西(null
和 undefined
除外),它默认存储值并在您再次使用相同的值调用它时返回它(不是特别有用但至少没有错误)。
对于null
或undefined
会报错
生命周期和范围
有两种终身注册类型:
singleton
在容器的生命周期内给出相同的实例
transient
每次调用容器时都会提供一个新实例
singleton
的生命周期进一步取决于它注册到的容器的生命周期,在典型的 child 容器的情况下,是视图模型的生命周期。
API表面的其他部分本质上只是singleton
或transient
的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")
是我个人认为有时调试非常方便的东西:)
在 Aurelia (+ TypeScript) 中...
有没有办法在上下文中(例如在视图模型中)直接引用容器并从中显式 "request" 个新实例?
要在您的 view-model 中获取容器,您 通常 有 3 个选项:
1。注入容器
用 @inject(Container)
装饰你的视图模型或者简单地应用 any 装饰器(这使得 tsc 发出类型元数据)并确保在你的构造函数中指定类型,如下所示:
constructor(private container: Container) {}
这是获取容器的推荐方法,因为它会给你 child 容器范围内的特定视图模型。这意味着,如果您请求 Element
或 Router
之类的内容,您还将获得范围限于该视图模型的内容。
您注册到该容器的内容只能通过该容器或其 children 解析 - 而不是其兄弟或 parents.
2。使用全局容器
总有一个 "root" 容器,您可以通过 Container.instance
静态 属性.
这对于某些在正常 aurelia 生命周期之外存在的组件很有用,或者如果您确实需要 root。你会想尽可能避免这种情况,因为它会导致意大利面条代码。
3。 "Abuse"路由器
我不一定会推荐这个,但每个配置的路由器上总是有一个 .container
属性。这是作用域 child 路由器 - 如果将它注入到视图模型的构造函数中,就会得到相同的路由器。
引用容器后:
调用 container.get(Foo)
,仅从该容器中获取 Foo
的实例,或调用 container.getAll(Foo)
从该容器中获取所有 Foo
的列表及其所有 parents,直到根。
对于构造函数,它默认调用构造函数并递归解析其依赖项(如果有)。然后它将实例存储为 单例.
对于任何不是构造函数的东西(
null
和undefined
除外),它默认存储值并在您再次使用相同的值调用它时返回它(不是特别有用但至少没有错误)。对于
null
或undefined
会报错
生命周期和范围
有两种终身注册类型:
singleton
在容器的生命周期内给出相同的实例transient
每次调用容器时都会提供一个新实例
singleton
的生命周期进一步取决于它注册到的容器的生命周期,在典型的 child 容器的情况下,是视图模型的生命周期。
API表面的其他部分本质上只是singleton
或transient
的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")
是我个人认为有时调试非常方便的东西:)