从Aurelia依赖注入容器中显式请求新实例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从Aurelia依赖注入容器中显式请求新实例相关的知识,希望对你有一定的参考价值。
在Aurelia(+ TypeScript)......
有没有办法在上下文中直接引用容器(例如在视图模型中)并明确地“请求”它的新实例?
要在视图模型中获取容器,通常有3个选项:
1. Inject the container
使用@inject(Container)
装饰你的viewmodel或者只是应用任何装饰器(这使得tsc发出类型元数据)并确保在你的构造函数中指定类型,如下所示:
constructor(private container: Container) {}
这是获取容器的推荐方法,因为它将为您提供作用于该特定视图模型的子容器。这意味着如果您要求Element
或Router
之类的东西,您还可以获得那些视图模型的范围。
您注册到该容器的东西只能通过该容器或其子容器(而不是其兄弟姐妹或父母)进行解析。
2. Use the global container
总有一个“根”容器,您可以通过Container.instance
静态属性访问代码中的任何位置。
这对于某些生活在正常aurelia生命周期之外的组件,或者如果你真的需要root,这可能很有用。你可以尽量避免这种情况,因为它会导致意大利面条代码。
3. "Abuse" the router
我不一定会推荐这个,但每个配置的路由器上总有一个.container
属性。这是作用域子路由器 - 如果将其注入视图模型的构造函数中,则会获得相同的路由器。
一旦你有了对容器的引用:
调用container.get(Foo)
,只从该容器中获取Foo
的实例,或者调用container.getAll(Foo)
以获取该容器及其所有父项的所有Foo
列表,直至根目录。
- 对于构造函数,它默认调用构造函数并以递归方式解析其依赖项(如果有的话)。然后它将实例存储为单例。
- 对于任何不是构造函数的东西(除了
null
和undefined
),它默认存储值并且每当你再次使用相同的值调用它时返回它(不是特别有用,但至少没有错误)。 - 对于
null
或undefined
,它会抛出错误。
Lifetime and scope
有两种生命周期注册类型:
singleton
为容器的生命周期提供相同的实例transient
每次调用容器时都会给出一个新实例
singleton
的生命周期进一步取决于它所注册的容器的生命周期,在典型的子容器的情况下,它是视图模型的生命周期。
API表面的其他部分基本上只是singleton
或transient
的不同范围的变体。
Setting the registration type
这里有很多选择,我不会在这里讨论所有这些选项。与您相关的是直接容器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))
(对于具有单身Foo
的瞬态Bar
)
还有其他选择,但这些是最常用的选项。
最后关于key, fn
论点的说明:调用register(Foo)
相当于调用register(Foo, Foo)
。你也可以说register("foo", Foo)
如果你不想/没有你想要调用它的类名的引用。
能够打开调试器并说document.body.aurelia.container.get("foo")
是我个人觉得有时调试很方便:)
以上是关于从Aurelia依赖注入容器中显式请求新实例的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core依赖注入高级玩法——如何注入多个服务实现类
IOC 控制反转Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )(代码片