2017-02-07 3 views
3

Ich bin vertraut mit Aurelia und Dependency Injection. Allerdings verstehe ich die folgende Zeile aus dem Buch "Learning Aurelia" auf Packtpub.com im Kapitel Dependency Injection nicht.Was sind Container in Aurelia Dependency Injection

In Aurelia kann ein Container untergeordnete Container erstellen, die selbst ihre eigenen untergeordneten Objekte erstellen und ausgehend vom Stammcontainer der Anwendung einen Baum von Containern bilden können. Jeder untergeordnete Container erbt die Dienste seines übergeordneten Elements, kann jedoch eigene registrieren, um die übergeordneten Elemente zu überschreiben.

I DI verwenden wie in dem Beispiel in dem Buch:

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(); 
} 
} 

Aber woher kommt der Behälter in diesen passen? Ich habe niemals einen Container im Code referenziert. Ich habe keine Kindercontainer erstellt. Es heißt "Jeder untergeordnete Container erbt die Dienste seiner Eltern." Ich habe Komponenten mit vielen untergeordneten Komponenten, die separate Ansichten und Ansichtsmodelle sind. Ich verstehe nicht, wie Container hineinpassen. Wie würden die Viewmodels auf Dienste des Elternteils zugreifen?

Fehle ich etwas?

Antwort

4

Aurelia hat eine Implementierung eines Dependency Injection Container, die sie verwendet Viewmodels zu instanziiert und viele der Anwendungsdienste, die Teil des Rahmens sind oder geschrieben von Entwicklern. In der Regel müssen Sie den Container nicht direkt verwenden, da das Conventions-System von Aurelia den Container zum Erstellen von Ansichtsmodellen und -Diensten in Ihrem Namen verwendet und @inject und @autoinject es nicht erforderlich machen, den Container manuell zu konfigurieren.

Was ist ein Abhängigkeitsinjektionsbehälter?Nun ein Behälter ist ein anderes Wort für einen Injektor:

Der Injektor stellt die Dienste in den Client. Oft baut es auch den Client. Ein Injektor kann eine sehr komplexe Objektgrafik verbinden, indem er ein Objekt wie einen Client und später als einen Dienst für einen anderen Client behandelt. Der Injektor kann tatsächlich viele Objekte sein, die zusammenarbeiten, ist aber möglicherweise nicht der Client. Der Injektor kann mit anderen Namen bezeichnet werden, wie zum Beispiel: Assembler, Provider, Container, Fabrik, Builder, Feder, Konstruktionscode oder Haupt. - https://en.wikipedia.org/wiki/Dependency_injection

Aureliens Behältersystem ist hierarchisch aufgebaut, was bedeutet, wenn Sie @inject oder @autoinject etwas, der Strom (Kind) Container werden für das Element gesucht werden, und wenn es nicht gefunden wird, wird der übergeordnete Container gesucht und usw., bis das Objekt gefunden oder der Root-Container gefunden wird. In diesem Fall erstellt Aurelia eine neue Instanz des angeforderten Objekts.

In Ihrem Code-Snippet Sie haben:

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(); 
    } 
} 

Unter der Annahme, das ist ein Blick-Modells individuelle Element ist, das Sie wie folgt verwendet werden: <person-list></person-list>, hier ist, was passieren wird, wenn Aurelia die PersonList instanziiert.

  1. Ein untergeordneter Container wird aus dem aktuellen Container erstellt (mehr zu dem, was der "aktuelle Container" später ist). Entspricht dem Aufruf container.createChildContainer(). Wir nennen diesen untergeordneten Container "childContainer".
  2. Kontextelemente werden im untergeordneten Container registriert, z. B. das DOM-Element (die Ansicht) für das View-Modell PersonList. Dies entspricht dem Aufruf childContainer.registerInstance(Element, personListDomElement). Warum? Denn dadurch können Entwickler @inject(Element) (oder @autoinject gleichwertig).
  3. Sobald der untergeordnete Container konfiguriert ist, wird er verwendet, um eine Instanz der PersonList zu erstellen. Äquivalent Aufruf:

    personList = childContainer.invoke(PersonList); 
    childContainer.registerInstance(PersonList, personList); 
    
  4. Das Kind Container nichts mit dem Schlüssel registriert hat „PersonService“, so dass es übergeordneten Container ist durchsucht werden, bis es gefunden oder nicht gefunden werden kann, in welchem ​​Fall Aurelia ein Konstrukt neue Instanz von PersonService und registrieren Sie sie im Stammcontainer, damit die Instanz in nachfolgenden Suchvorgängen wiederverwendet werden kann.

  5. Die Personenliste viewmodel und view werden von der Templating-Engine erstellt, und die Lebenszyklusereignisse created, bind, attached etc passieren.

Bonus: ich früher erwähnt ein Kind Behälter aus dem aktuellen Container erstellt werden ... Jede Aurelia Anwendung verfügt über eine „Root-Ebene“ Container, der jedes Kind Container aus, die direkt oder indirekt absteigt. Aurelias Kern-Anwendungsdienste sind im Root-Container registriert: BindingEngine, ObserverLocator, TaskQueue und viele mehr. Dies ermöglicht Entwicklern, @inject(TaskQueue) zu schreiben und dieselbe TaskQueue-Instanz zu erhalten, die das Aurelia-Framework intern verwendet. Wenn ein benutzerdefiniertes Element oder ein benutzerdefiniertes Attribut instanziiert wird, wird ein untergeordneter Container verwendet, um das benutzerdefinierte Element oder benutzerdefinierte Attribut zu erstellen. Wenn dieses benutzerdefinierte Element ein anderes benutzerdefiniertes Element enthält, wird ein untergeordneter Container aus dem aktuellen untergeordneten Container erstellt und zum Instanziieren des untergeordneten benutzerdefinierten Elements usw. verwendet.Mit anderen Worten, der "aktuelle Container" hängt davon ab, wie tief Ihre Komponente in einer Hierarchie von geschachtelten benutzerdefinierten Elementen und benutzerdefinierten Attributen liegt.

Links:

2

Im Allgemeinen müssen Sie den Container nicht direkt referenzieren. Aurelia wird das für Sie übernehmen, wenn es Ihre Komponenten (Seiten, benutzerdefinierte Elemente, benutzerdefinierte Attribute, Wertkonverter usw.) instanziieren muss.

Der DI Container kann als Stammbaum betrachtet werden. Es gibt einen Container auf App-Ebene, zu dem alle anderen Container gehören. Für jede Komponente wird ein neuer untergeordneter Container erstellt.

Es gibt Helfer, die Sie verwenden können, um dem Container Informationen darüber zu geben, wie er mit den Dingen umgehen soll. Sie erhalten das Standardverhalten unter Verwendung von @autoinject, aber wenn Sie genauer sein müssen, können Sie auf @inject Dekorateur umschalten und Dinge wie @inject(Parent.of(Foo), Optional.of(Bar)) oder etwas tun. Dadurch erhalten Sie eine Instanz der Klasse Foo, die im übergeordneten Container erstellt wurde, und teilt dem Container mit: "Ich hätte gerne eine Instanz von Bar, aber es ist cool, wenn Sie sie nicht für mich erstellen können."

Wenn Sie Zugriff auf die VM des Parent benötigen, können Sie Parent.of() verwenden, um es in einer untergeordneten Komponente abzurufen. Beachten Sie, dass dies einer dieser "Handle with care" -Dinge ist, da Sie eine untergeordnete Komponente direkt an die Implementierung der Parent-VM binden und die Komponente nicht erstellen (und möglicherweise die App abstürzen lässt), wenn Sie sie innerhalb verwenden Eine Seite/Komponente mit einer anderen VM-Klasse.

Für weitere Informationen besuchen Sie bitte unsere docs aus: http://aurelia.io/hub.html#/doc/article/aurelia/dependency-injection/latest/dependency-injection-basics