vscode源码分析【六】服务实例化和单例的实现

第一篇: vscode源码分析【一】从源码运行vscode
第二篇:vscode源码分析【二】程序的启动逻辑,第一个窗口是如何创建的
第三篇:vscode源码分析【三】程序的启动逻辑,性能问题的追踪
第四篇:vscode源码分析【四】程序启动的逻辑,最初创建的服务
第五篇:vscode源码分析【五】事件分发机制

细心的读者可能会发现,在第四篇文章中的createService方法中,并没有把所有的服务实例化,下面这些服务,只是记了他们的类型:
src\vs\code\electron-main\main.ts

		services.set(ILifecycleService, new SyncDescriptor(LifecycleService));
		services.set(IStateService, new SyncDescriptor(StateService));
		services.set(IRequestService, new SyncDescriptor(RequestService));
		services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
		services.set(IThemeMainService, new SyncDescriptor(ThemeMainService));
		services.set(ISignService, new SyncDescriptor(SignService));

SyncDescriptor负责记录这些服务的类型,以供后续使用
(src\vs\platform\instantiation\common\descriptors.ts)

export class SyncDescriptor<T> {
	readonly ctor: any;
	readonly staticArguments: any[];
	readonly supportsDelayedInstantiation: boolean;
	constructor(ctor: new (...args: any[]) => T, staticArguments: any[] = [], supportsDelayedInstantiation: boolean = false) {
		this.ctor = ctor;
		this.staticArguments = staticArguments;
		this.supportsDelayedInstantiation = supportsDelayedInstantiation;
	}
}

接下来,main.ts的startup方法内,就实例化了这些服务

			await instantiationService.invokeFunction(async accessor => {
				const environmentService = accessor.get(IEnvironmentService);
				const configurationService = accessor.get(IConfigurationService);
				const stateService = accessor.get(IStateService);
				try {
					await this.initServices(environmentService, configurationService as ConfigurationService, stateService as StateService);
				} catch (error) {

					// Show a dialog for errors that can be resolved by the user
					this.handleStartupDataDirError(environmentService, error);

					throw error;
				}
			});

这里accessor的get方法如下:(src\vs\platform\instantiation\common\instantiationService.ts)

				get: <T>(id: ServiceIdentifier<T>, isOptional?: typeof optional) => {

					if (_done) {
						throw illegalState('service accessor is only valid during the invocation of its target method');
					}

					const result = this._getOrCreateServiceInstance(id, _trace);
					if (!result && isOptional !== optional) {
						throw new Error(`[invokeFunction] unknown service '${id}'`);
					}
					return result;
				}

有个_getOrCreateServiceInstance方法:

	private _getOrCreateServiceInstance<T>(id: ServiceIdentifier<T>, _trace: Trace): T {
		let thing = this._getServiceInstanceOrDescriptor(id);
		if (thing instanceof SyncDescriptor) {
			return this._createAndCacheServiceInstance(id, thing, _trace.branch(id, true));
		} else {
			_trace.branch(id, false);
			return thing;
		}
	}

你发现,如果它想获取的对象是SyncDescriptor类型的,就会创建并缓存相应的对象
这个方法_createAndCacheServiceInstance负责创建对象的实例(暂时先不解释)
下次获取这个对象的时候,就直接从缓存中获取了
 

posted @   liulun  阅读(1240)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
历史上的今天:
2014-06-19 分享我用Qt开发的应用程序【二】在Qt应用程序中使用字体图标fontawesome
2013-06-19 基于.net开发chrome核心浏览器【五】
2011-06-19 PL-SQL温习
点击右上角即可分享
微信分享提示