Heim > Artikel > Entwicklungswerkzeuge > Sprechen Sie kurz über das Prinzip der Abhängigkeitsinjektion in VSCode
Dieser Artikel gibt Ihnen eine kurze Analyse des Prinzips der Abhängigkeitsinjektion in VSCode. Lassen Sie uns darüber sprechen, was die Abhängigkeitsinjektion bewirkt. Wie führt man eine Abhängigkeitsinjektion durch? Hoffe, es hilft allen!
Das Team fördert „Dependency Injection“ schon seit einiger Zeit, aber jedes Mal, wenn es verwendet wird, fühlt es sich seltsam an. Es gibt viele Konzepte, die immer unklar sind: Service-ID, Service-Deskriptor, Service-Dekorator usw.
Vielleicht liegt es daran, dass ich die Prinzipien nicht verstehe und es sich bei der Verwendung „virtuell“ anfühlt. Ich habe kürzlich versucht, die Prinzipien zu klären, indem ich den Quellcode von VS Code und die von Teamleitern geteilten Artikel gelesen habe Kern Logische Einführung.
class B {} class A { constructor() { // 在 A 的构造器中 new B this.b = new B(); } } class Feature { constructor() { this.a = new A(); this.b = new B(); } } // 使用时 const feature = new Feature();
vscode-Tutorial
,class A { constructor(b: B) { this.b = b; } } class Feature { constructor(a, b) { this.a = a; this.b = b; } } // 使用时 const b = new B(); const a = new A(b); const feature = new Feature(a, b);Bei der Initialisierung eines Moduls werden die Module, von denen es abhängt, zunächst extern erstellt und in Form von Parametern an das Funktionsmodul übergeben. Diese Schreibweise ist „Dependency Injection“. Das Problem bei dieser Schreibweise besteht nun darin, dass bei der manuellen Parameterübertragung die Reihenfolge von new manuell garantiert werden muss, das heißt, Instanzen von a und b müssen abgerufen werden, bevor new ausgeführt werden kann. Besonderheit. Wenn Abhängigkeiten komplex werden, sind wahrscheinlich unzählige Basismodule erforderlich, bevor ein Funktionsmodul erstellt wird, und die Komplexität wird zu diesem Zeitpunkt sehr hoch sein. Ähnlich wie dieses Gefühl:
Stellen Sie sich ein Modell vor: Es gibt einen Modulcontroller oder „Dienstmanager“, der diese Abhängigkeiten verwaltet:
class Feature { // 声明这个模块依赖 idA, idB idA idB } // 告知「服务管理器」,怎么找对应的模块 services[idA] = A; services[idB] = B; // 使用时 const feature = services.createInstance(Feature);
Trägt dieser Dienst nicht den vorherigen „manuellen“ Prozess?
Wenn Sie eine Instanz erstellen (Feature), analysieren Sie die Module, von denen das Feature abhängt:Wenn das Modul, von dem es abhängt, keine Instanz erstellt hat, erstellen Sie die Dienstinstanz rekursiv und kehren Sie schließlich zurück on hat keine Instanz erstellt. Wenn eine Instanz vorhanden ist, geben Sie die Instanz zurück.
Abhängigkeitsinformationen hinzufügen
Zusammenfassen Sie das Problem noch einmal:
Wie füge ich einer Klasse zusätzliche Informationen hinzu?Dies kann einfach durch Schreiben des „Parameter Decorators“ erfolgen:
// 参数装饰器 const decorator = ( target: Object, // 被装饰的目标,这里为 Feature propertyName: string, index: number // 参数的位置索引 ) => { target['deps'] = [{ index, id: 'idA', }]; } class Feature { name = 'feature'; a: any; constructor( // 参数装饰器 @decorator a: any, ) { this.a = a; } } console.log('Feature.deps', Feature['deps']); // [{ id: 'idA', index: 0 }]
Verwenden Sie Karte für die Verwaltung, eine ID entspricht einem Dienstleiter.
class A { name = 'a'; } // 服务集 class ServiceCollection { // 服务集合 // key 为服务标识 // value 为 服务ctor private entries = new Map<string, any>(); set(id: string, ctor: any) { this.entries.set(id, ctor); } get(id: string): any { return this.entries.get(id); } } const services = new ServiceCollection(); // 声明服务 A id 为 idA services.set('idA', A);
// 通过 Feature 找到所依赖的 A const serviceId = Feature['deps'][0].id; // idA console.log( 'Feature.deps', services.get(serviceId) // A );
Die spezifische Idee ist:
Wenn das abhängige Modul Wenn noch keine Instanz erstellt wurde, wird die Dienstinstanz rekursiv erstellt und schließlich zurückgegeben.class InstantiationService { services: ServiceCollection; constructor(services: ServiceCollection) { this.services = services; } createInstance(ctor: any) { // 1. 获取 ctor 依赖的 服务id // 结果为: ['idA'] const depIds = ctor['deps'].map((item: any) => item.id); // 2. 获取服务 id 对应的 服务构造器 // 结果为:[A] const depCtors = depIds.map((id: string) => services.get(id)); // 3. 获取服务实例 // 结果为: [ A { name: 'a'} ] const args = depCtors.map((ctor: any) => new ctor()); // 4. 依赖的服务作为参数注入,实例化所需要模块 // 结果为:[ Feature { name: 'feature', a }] const result = new ctor(...args); return result; } } const instantiation = new InstantiationService(services); // 使用时 const feature = instantiation.createInstance(Feature);
Dieser Artikel implementiert lediglich ein „Abhängigkeitsinjektions“-Modell auf Demoebene, das einfach Folgendes implementiert:
erforderliche Abhängigkeiten für die Moduldeklaration;
Modulerstellung;
Auf dieser Grundlage können einige erweiterte Funktionen erweitert werden:
Modulerstellung (rekursiv): VSCode verwendet dazu Stapel + Diagramm, und der Algorithmus ist nicht kompliziert;
Abhängigkeitssammlung: kann zum Analysieren verwendet werden Abhängigkeiten jedes Moduls und erkennen, ob es „zyklische Abhängigkeiten“ gibt;
Modulzerstörung: Wenn das Modul zerstört wird, zerstören Sie rekursiv die Dienstinstanzen, von denen es abhängt;
Verzögerte Initialisierung: Wählen Sie beim Erstellen abhängiger Dienste Erstellen Sie einen Proxy, und die Instanz wird nur erstellt, wenn sie tatsächlich verwendet wird.
Asynchrone Abhängigkeit: So führen Sie die Erstellungslogik aus, wenn der Erstellungsprozess des abhängigen Dienstes asynchron ist.
Vollständige Funktionen Weitere Informationen finden Sie im Code, der vom gesamten Abhängigkeitsinjektionssystem von VSCode geschrieben wurde.
ReferenzmaterialienVS-Code-Quellcode-Speicherort: src/vs/platform/instantiation/common
vscode-Tutorial
Das obige ist der detaillierte Inhalt vonSprechen Sie kurz über das Prinzip der Abhängigkeitsinjektion in VSCode. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!