gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

詳細分析一下VSCode中的依賴注入

詳細分析一下VSCode中的依賴注入

php入門到就業線上直播課:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

在閱讀 VSCode 代碼的過程中,我們會發現每一個模塊中都有大量裝飾器的使用,用來裝飾模塊以及其中依賴的模塊變量。這樣做的目的是什么呢?在這一篇中我們來詳細分析一下。【推薦學習:vscode教程、編程視頻】

依賴注入介紹

如果有這樣一個模塊 A,它的實現依賴另一個模塊 B 的能力,那么應該如何設計呢?很簡單,我們可以在 A 模塊的構造函數中實例化模塊 B,這樣就可以在模塊 A 內部使用模塊 B 的能力了。

class A {   constructor() {     this.b = new B();   } }  class B {}  const a = new A();
登錄后復制

但是這樣做有兩個問題,一是模塊 A 的實例化過程中,需要手動實例化模塊 B,而且如果模塊 B 的依賴關系發生變化,那么也需要修改模塊 A 的構造函數,導致代碼耦合。

二是在復雜項目中,我們在實例化模塊 A 時,難以判斷模塊 B 是否被其他模塊依賴而已經實例化過了,從而可能將模塊 B 多次實例化。若模塊 B 較重或者需要為單例設計,這將帶來性能問題。

因此,更好的方式是,將所有模塊的實例化交給外層框架,由框架統一管理模塊的實例化過程,這樣就可以解決上述兩個問題。

class A {   constructor(private b: B) {     this.b = b;   } }  class B {}  class C {   constructor(private a: A, private b: B) {     this.b = b;   } }  const b = new B(); const a = new A(b); const c = new C(a, b);
登錄后復制

這種將依賴對象通過外部注入,避免在模塊內部實例化依賴的方式,稱為依賴注入 (Dependencies Inject, 簡稱 DI)。這在軟件工程中是一種常見的設計模式,我們在 Java 的 Spring,JS 的 Angular,Node 的 NestJS 等框架中都可以看到這種設計模式的應用。

當然,在實際應用中,由于模塊眾多,依賴復雜,我們很難像上面的例子一樣,規劃出來每個模塊的實例化時機,從而編寫模塊實例化順序。并且,許多模塊可能并不需要第一時間被創建,需要按需實例化,因此,粗暴的統一實例化是不可取的。

因此我們需要一個統一的框架來分析并管理所有模塊的實例化過程,這就是依賴注入框架的作用。

借助于 TypeScript 的裝飾器能力,VSCode 實現了一個極為輕量化的依賴注入框架。我們可以先來簡單實現一下,解開這個巧妙設計的神秘面紗。

最簡依賴注入框架設計

實現一個依賴注入框架只需要兩步,一個是將模塊聲明并注冊到框架中進行管理,另一個是在模塊構造函數中,聲明所需要依賴的模塊有哪些。

我們先來看模塊的注冊過程,這需要 TypeScript 的類裝飾器能力。我們在注入時,只需要判斷模塊是否已經注冊,如果沒有注冊,將模塊的 id(這里簡化為模塊 Class 名稱)與類型傳入即可完成單個模塊的注冊。

export function Injectable(): ClassDecorator {   return (Target: Class): any => {     if (!collection.providers.has(Target.name)) {       collection.providers.set(Target.name, target);     }     return target;   }; }
登錄后復制

之后我們再來看看模塊是如何聲明依賴的,這需要 TypeScript 的屬性裝飾器能力。我們在注入時,先判斷依賴的模塊是否已經被實例化,如果沒有,則將依賴模塊進行實例化,并存入框架中管理。最終返回已經被實例化完成的模塊實例。

export function Inject(): PropertyDecorator {   return (target: Property, propertyKey: string) => {      const instance = collection.dependencies.get(propertyKey);     if (!instance) {       const DependencyProvider: Class = collection.providers.get(propertyKey);       collection.dependencies.set(propertyKey, new DependencyProvider());     }      target[propertyKey] = collection.dependencies.get(propertyKey);   }; }
登錄后復制

最后只需要保證框架本身在項目運行前完成實例化即可。(在例子中表示為 injector)

export class ServiceCollection {   readonly providers = new Map<string, any>();   readonly dependencies = new Map<string, any>(); }  const collection = new ServiceCollection(); export default collection;
登錄后復制

這樣,一個最簡化的依賴注入框架就完成了。由于保存了模塊的類型與實例,它實現了模塊的按需實例化,無需在項目啟動時就初始化所有模塊。

我們可以嘗試調用它,以上面舉出的例子為例:

@injectable() class A {   constructor(@inject() private b: B) {     this.b = b;   } }  @injectable() class B {}  class C {   constructor(@inject() private a: A, @inject() private b: B) {     this.b = b;   } }  const c = new C();
登錄后復制

無需知曉模塊 A,B 的實例化時機,直接初始化任何一個模塊,框架會自動幫你找到并實例化好所有依賴的模塊。

VSCode 的依賴收集實現

上面介紹了一個依賴注入框架的最簡實現。但當我們真正閱讀 VSCode 的源碼時,我們發現 VSCode 中的依賴注入框架貌似并不是這樣消費的。

例如在下面這段鑒權服務中,我們發現該類并沒有@injectable()作為類的依賴收集,并且依賴服務也直接用其類名作為修飾器,而不是@inject()

// srcvsworkbenchservicesauthenticationbrowserauthenticationService.ts export class AuthenticationService extends Disposable implements IAuthenticationService {   constructor(     @IActivityService private readonly activityService: IActivityService,     @IExtensionService private readonly extensionService: IExtensionService,     @IStorageService private readonly storageService: IStorageService,     @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,     @IDialogService private readonly dialogService: IDialogService,     @IQuickInputService private readonly quickInputService: IQuickInputService   ) {} }
登錄后復制

其實這里的修飾符并不是真正指向類名,而是一個同名的資源描述符 id(VSCode 中稱之為 ServiceIdentifier),通常使用字符串或 Symbol 標識。

通過 ServiceIdentifier 作為 id,而不是簡單粗暴地通過類名稱作為 id 注冊 Service,有利于處理項目中一個 interface 可能存在多態實現,需要同時多個同名類實例的問題。

此外,在構造 ServiceIdentifier 時,我們便可以將該類聲明注入框架,而無需@injectable()顯示調用了。

那么,這樣一個 ServiceIdentifier 該如何構造呢?

// srcvsplatforminstantiationcommoninstantiation.ts /**  * The *only* valid way to create a {{ServiceIdentifier}}.  */ export function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {    if (_util.serviceIds.has(serviceId)) {     return _util.serviceIds.get(serviceId)!;   }    const id = <any>function (target: Function, key: string, index: number): any {     if (arguments.length !== 3) {       throw new Error('@IServiceName-decorator can only be used to decorate a parameter');     }     storeServiceDependency(id, target, index);   };    id.toString = () => serviceId;    _util.serviceIds.set(serviceId, id);   return id; }  // 被 ServiceIdentifier 裝飾的類在運行時,將收集該類的依賴,注入到框架中。 function storeServiceDependency(id: Function, target: Function, index: number): void {   if ((target as any)[_util.DI_TARGET] === target) {     (target as any)[_util.DI_DEPENDENCIES].push({ id, index });   } else {     (target as any)[_util.DI_DEPENDENCIES] = [{ id, index }];     (target as any)[_util.DI_TARGET] = target;   } }
登錄后復制

我們僅需通過createDecorator方法為類創建一個唯一的ServiceIdentifier,并將其作為修飾符即可。

以上面的 AuthenticationService 為例,若所依賴的 ActivityService 需要變

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
日韩成人av免费| 激情综合网俺也去| 国产最新免费视频| 日韩不卡一二区| av污在线观看| 国产3p在线播放| 奇米影视四色在线| 亚洲 欧美 日韩系列| av视屏在线播放| 激情内射人妻1区2区3区| 免费国产黄色网址| 黄色三级中文字幕| 免费视频爱爱太爽了| 天堂а√在线中文在线| 特色特色大片在线| 日韩一二区视频| 欧美精品久久久久久久自慰| 成人在线播放网址| 777精品久无码人妻蜜桃| 成人一对一视频| 久久综合久久色| 亚洲精品成人在线播放| 亚洲一级片免费观看| www.18av.com| 成人观看免费完整观看| 香蕉视频禁止18| 亚洲小视频网站| 日韩国产成人无码av毛片| 成人网站免费观看入口| aaa毛片在线观看| 亚洲制服在线观看| 99久久久精品视频| 538在线视频观看| 麻豆一区二区三区在线观看| 精品视频免费在线播放| 三级视频中文字幕| 国产日产欧美一区二区| 久久无码高潮喷水| 最近中文字幕免费mv| 亚洲熟妇av日韩熟妇在线| 日韩在线不卡一区| 精品国偷自产一区二区三区| 人妻无码视频一区二区三区| 一级特黄妇女高潮| 国产精品视频中文字幕| 日日摸日日碰夜夜爽无码| 第一区免费在线观看| 国产91美女视频| 欧美 亚洲 视频| 一女二男3p波多野结衣| 18禁网站免费无遮挡无码中文| 中文字幕中文在线| 任你操这里只有精品| 日韩一区二区高清视频| www.污网站| 欧美性猛交xxx乱久交| 青青青在线视频播放| 精品一区二区成人免费视频| 国产九九在线观看| 男人天堂网视频| 男女超爽视频免费播放| 丁香色欲久久久久久综合网| 色18美女社区| 日韩av片网站| 黄色av免费在线播放| 免费无码av片在线观看| 国产91在线视频观看| 17c丨国产丨精品视频| 手机福利在线视频| 免费不卡av网站| 午夜xxxxx| 欧美日韩在线免费观看视频| 中文字幕第一页在线视频| 国产精品视频黄色| 久久久精品三级| 亚洲精品自拍网| 国产又粗又猛大又黄又爽| 日本中文字幕二区| 加勒比av中文字幕| 欧美大片久久久| 涩涩网站在线看| 欧美三级午夜理伦三级老人| 久久久99精品视频| 国产深夜男女无套内射| 色综合av综合无码综合网站| 国产91色在线观看| 91免费网站视频| 被灌满精子的波多野结衣| 777精品久无码人妻蜜桃| 久久综合久久色| 四虎成人在线播放| 九九热只有这里有精品| 国产精品亚洲二区在线观看| jizz18女人| 97中文字幕在线| 免费在线观看毛片网站| 日本精品一区在线| 青青草综合在线| 精品日韩久久久| 欧美在线观看视频免费| 午夜精品久久久内射近拍高清| 欧美成人三级在线播放| 99久久国产综合精品五月天喷水| 欧美 日韩 国产一区| 97人人模人人爽人人澡| 国产日产欧美视频| 蜜臀av.com| 99免费视频观看| 精品视频在线观看一区二区| 自拍偷拍21p| 能在线观看的av| 亚洲精品天堂成人片av在线播放| 久久久精品在线视频| 久久免费一级片| 香港日本韩国三级网站| 一卡二卡三卡视频| 男女h黄动漫啪啪无遮挡软件| 国产精品亚洲a| 欧美国产综合在线| 夜夜爽久久精品91| 亚洲精品午夜在线观看| 国产免费成人在线| 六月婷婷激情综合| www.51色.com| 婷婷免费在线观看| 青青草av网站| 日韩一级在线免费观看| 精品久久久久久久久久中文字幕| 特色特色大片在线| 久久久一二三四| 亚洲AV无码成人精品一区| 亚洲国产高清av| 虎白女粉嫩尤物福利视频| 日本精品一区在线观看| 久久久久久久久久久99| 在线观看17c| av在线com| 欧美国产视频一区| 国产乱淫av片杨贵妃| 欧美一级欧美一级| 国产美女无遮挡网站| 无码人妻精品一区二区三区在线| 久久久亚洲国产精品| 精品国产免费av| 国产福利影院在线观看| 色天使在线观看| 九一精品久久久| 香蕉视频在线网址| 无码熟妇人妻av在线电影| 精品视频在线观看一区| 男人添女人下面高潮视频| 黄色一级大片在线观看| 精品久久久久久久无码 | 黄色小视频大全| 真人做人试看60分钟免费| 欧美国产亚洲一区| www.日日操| 欧美 国产 精品| 国产特级淫片高清视频| 污污动漫在线观看| 黄瓜视频免费观看在线观看www| www.亚洲成人网| 青青草精品视频在线观看| 色中文字幕在线观看| 全黄性性激高免费视频| 一道本视频在线观看| 日本精品福利视频| 日本成人在线免费视频| 成人性做爰片免费视频| 日韩av资源在线| 黄色网址在线免费看| 日韩免费一级视频| 亚洲一区二区中文字幕在线观看| 国产激情片在线观看| 香蕉视频禁止18| 国产精品久久..4399| 亚洲一区二区福利视频| 国产一区二区视频播放| www.五月天色| 国内外免费激情视频| 日本精品福利视频| 亚洲欧美日本一区二区三区| 国产午夜福利100集发布| 超碰在线免费av| 男人女人黄一级| www精品久久| 26uuu成人| 182午夜视频| 手机看片福利日韩| 国产精品一区二区免费在线观看| 大桥未久一区二区三区| 色播五月综合网| av黄色在线网站| 久久久久久久午夜| 欧美性猛交内射兽交老熟妇| 欧美特黄aaa| 天天插天天操天天射| 成熟老妇女视频| 毛葺葺老太做受视频| 成人一区二区三|