이 기사에서는 VSCode의 종속성 주입 원리에 대해 간략하게 분석합니다. 의존성 주입은 어떻게 하나요? 모두에게 도움이 되기를 바랍니다!
팀에서는 한동안 "의존성 주입"을 홍보해 왔지만 사용할 때마다 서비스 ID, 서비스 설명자, 서비스 데코레이터 등 항상 명확하지 않은 개념이 많이 있습니다.
원리를 이해하지 못하고 사용하면 '가상'처럼 느껴지기 때문일 수도 있지만, 최근에는 VS Code의 소스 코드와 팀 리더들이 공유한 기사를 읽으면서 원리를 명확히 하려고 노력했습니다. 핵심 논리 소개.
다음 상황을 가정해 보세요.
서비스 모듈 A, 서비스 B에 종속됨
서비스 모듈 B, 서비스 A에 종속됨 B;
일반적인 작성 방법에 따르면 다음과 같습니다.
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();
,
프로그래밍 교육]간단한 수정: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);
"입니다.
지금 이 쓰기 방식의 문제점은 수동 매개변수 전송 형식에서 new의 순서를 수동으로 보장해야 한다는 것입니다. 즉, new가 실행되기 전에 a와 b의 인스턴스를 얻어야 합니다. 특징. 종속성이 복잡해지면 기능적인 모듈을 만들기 전에 수많은 기본 모듈이 필요할 가능성이 높으며 이때 복잡성은 매우 높아질 것입니다. 이 느낌과 비슷합니다.
모델을 상상해 보세요. 이러한 종속성을 관리하는 모듈 컨트롤러 또는 "서비스 관리자"가 있습니다.class Feature { // 声明这个模块依赖 idA, idB idA idB } // 告知「服务管理器」,怎么找对应的模块 services[idA] = A; services[idB] = B; // 使用时 const feature = services.createInstance(Feature);
의존하는 모듈이 인스턴스를 생성하지 않은 경우 서비스 인스턴스를 재귀적으로 생성하고 최종적으로
해당하는 모듈을 반환합니다. 인스턴스가 생성되지 않은 경우 인스턴스를 반환합니다.
모든 항목을 찾은 후 매개변수를 통해 Feature를 주입하여 초기화를 완료합니다.
VSCode는 이러한 "종속성 주입 시스템"을 정확하게 구현합니다.클래스가 종속된 서비스 ID를 어떻게 선언합니까? 즉, 클래스가 주어지면 외부에서는 해당 클래스가 어떤 서비스에 의존하는지 어떻게 알 수 있습니까?
관리 서비스는 어떻게 관리하나요?
모듈을 만드는 방법은 무엇입니까?
다음은 주요 프로세스를 다루는 가장 간단한 모델을 구현합니다.
사실 es5에서는 모든 클래스가 함수이고 최종 분석에서는 모든 함수가 객체일 뿐입니다. 필요한 서비스 ID를 식별하기 위해 객체에 몇 가지 필드를 추가하면 필요한 기능이 완성될 수 있습니다.
이 작업은 "매개변수 데코레이터"를 작성하여 쉽게 수행할 수 있습니다. // 参数装饰器
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 }]
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 );
종속 모듈이 still has 인스턴스가 생성되지 않은 경우 서비스 인스턴스가 재귀적으로 생성되어 최종적으로 반환됩니다.
의존하는 모듈에 이미 인스턴스가 있는 경우 해당 인스턴스를 반환합니다.
모든 기능을 찾은 후 기능을 삽입합니다. 매개변수를 통해 초기화를 완료합니다.
먼저 종속성 계층이 하나만 있는 간단한 데모가 있습니다(즉, 종속 서비스는 다른 서비스에 종속되지 않습니다). :
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);
이 문서는 단순히 다음을 구현하는 데모 수준의 "종속성 주입" 모델을 구현합니다.
모듈 선언 필수 종속성
모듈 생성;
여기에서 이 기사의 코드를 참조하세요.
참조 자료
VS 코드 소스 코드 위치: src/vs/platform/instantiation/common이 문서는 코드 아이디어를 바탕으로 하며 이름 지정도 매우 일관적입니다. (수동 개 머리
!
위 내용은 VSCode의 종속성 주입 원리에 대해 간략하게 설명합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!