什么是Aurelia Dependency Injection中的容器

时间:2017-02-07 18:54:44

标签: javascript dependency-injection aurelia

我熟悉Aurelia和Dependency Injection。但是,我不理解Packtpub.com上的“Learning Aurelia”一书中的以下一行,在依赖注入章节中。

  

在Aurelia中,容器可以创建子容器,子容器本身可以创建自己的子容器,从应用程序的根容器开始形成容器树。每个子容器都继承其父容器的服务,但可以注册自己的容器以覆盖其父容器。

我在本书的例子中使用了DI:

import {PersonService} from 'app-services'; 
import {Person} from 'models'; 
import {autoinject} from 'aurelia-framework'; 

@autoinject 
export class PersonList { 

constructor(private personService: PersonService) { 
} 

getPeople(){ 
    return this.personService.getAll(); 
 } 
} 

但容器在哪里适合这个?我还没有在代码中引用容器。我还没有创建任何子容器。它说“每个子容器都继承了父容器的服务。”我有许多子组件的组件,它们是单独的视图和视图模型。我不明白容器是如何装入它的。 viewmodels如何访问父项的服务?

我错过了什么吗?

2 个答案:

答案 0 :(得分:4)

Aurelia有一个依赖注入容器的实现,它用于实例化视图模型和许多作为框架一部分或由开发人员编写的应用程序服务。通常,您不需要直接使用容器,因为Aurelia的约定系统使用容器代表您构建视图模型和服务,@inject@autoinject使得无需手动配置容器。

什么是依赖注入容器?那么容器注入器的另一个词:

  

注入器将服务引入客户端。通常,它也构建客户端。注入器可以通过将对象(如客户端)处理并随后作为另一客户端的服务来将非常复杂的对象图连接在一起。注射器实际上可能是许多物体一起工作但可能不是客户端。注入器可以用其他名称来指代,例如:汇编程序,提供程序,容器,工厂,构建器,弹簧,构造代码或主程序。    - https://en.wikipedia.org/wiki/Dependency_injection

Aurelia的容器系统是分层的,这意味着当您@inject@autoinject时,将搜索当前(子)容器以查找该项目,如果找不到,则将搜索父容器等等,直到找到项目或根容器被命中,在这种情况下,Aurelia将构造所请求项目的新实例。

在您的代码段中,您有:

import {PersonService} from 'app-services'; 
import {Person} from 'models'; 
import {autoinject} from 'aurelia-framework'; 

@autoinject 
export class PersonList { 

  constructor(private personService: PersonService) { 
  } 

  getPeople(){ 
    return this.personService.getAll(); 
  } 
}

假设这是您正在使用的自定义元素的视图模型:<person-list></person-list>,这是Aurelia实例化PersonList时会发生的情况。

  1. 将从当前容器创建子容器(更多关于“当前容器”的内容)。相当于调用container.createChildContainer()。我们将此子容器称为“childContainer”。
  2. 上下文项将在子容器中注册,例如PersonList视图模型的DOM元素(视图)。这相当于调用childContainer.registerInstance(Element, personListDomElement)。为什么?因为这使开发人员能够@inject(Element)(或等同于@autoinject)。
  3. 配置子容器后,它将用于创建PersonList的实例。相当于呼叫:

    personList = childContainer.invoke(PersonList);
    childContainer.registerInstance(PersonList, personList);
    
  4. 子容器没有使用键“PersonService”注册的任何内容,因此它的父容器将被搜索,直到找到或找不到,在这种情况下Aurelia将构造一个新实例PersonService并将其注册到根容器中,以便可以在后续查找中重用该实例。

  5. 人员列表视图模型和视图由模板引擎组成,并且创建,绑定,附加等生命周期事件发生。
  6. 奖励:之前我提到将从当前容器创建一个子容器 ...每个Aurelia应用程序都有一个“根级”容器,每个子容器直接或间接地从这个容器中下载。 Aurelia的核心应用程序服务在根容器中注册:BindingEngineObserverLocatorTaskQueue等等。这使开发人员能够编写@inject(TaskQueue)并获得Aurelia框架在内部使用的相同TaskQueue实例。无论如何,当实例化自定义元素或自定义属性时,子容器用于创建自定义元素或自定义属性。如果该自定义元素包含其他自定义元素,则将从当前子容器创建子容器,并用于实例化子自定义元素,依此类推。换句话说,“当前容器”取决于组件在嵌套自定义元素和自定义属性的层次结构中的深度。

    链接:

答案 1 :(得分:2)

通常,您不需要直接引用容器。当Aurelia需要实例化您的组件(页面,自定义元素,自定义属性,值转换器等)时,它将为您处理。

DI容器可以被认为是一个家谱。有一个应用级容器,所有其他容器都是子容器。每个组件都会获得一个为其创建的新子容器。

您可以使用帮助程序向容器提供有关如何处理内容的信息。您可以使用@autoinject获得默认行为,但如果您需要更具体,可以切换到@inject装饰器并执行@inject(Parent.of(Foo), Optional.of(Bar))之类的操作。这将为您提供在父容器中创建的Foo类的实例,并将告诉容器,&#34;我想要一个Bar的实例,但它&#39;如果你不能为我创造它,那就太酷了。&#34;

如果您需要访问父虚拟机,可以使用Parent.of()将其放入子组件中。请注意,这是其中之一&#34;谨慎处理&#34;输入内容,因为您将子组件直接绑定到父虚拟机的实现,如果您在具有不同内容的页面/组件中使用它,组件将无法创建(并可能使应用程序崩溃) VM类。

有关详细信息,请查看我们的文档:http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics