SharpDevelop原始碼分析 二 頭緒

2021-04-13 12:27:22 字數 3252 閱讀 2950

在大學課程裡面,我對於模擬電路總是搞不清楚,直到現在也是這樣。我總覺得電路圖很奇怪,總會問「這部分電路是做什麼用的」、「為什麼會有這樣的效果」。在我的腦海裡面,每部分的電路都應該有一定的用處,可是我總是看不明白。我媽媽說,我的思路被軟體所固化的太久了,看電路圖不應該總是乙個個模組的看,正確的方法應該是從電源的一極順著電路看,一直看到電源的另一極。我現在仍然不懂看電路圖,可是以我看**的經驗來說,我覺得分析源**按照這樣的思路來看會比較容易把脈絡理清楚。

在sharpdevelop的**中,由於很多的介面和外掛程式的原因,很多**在看到某個地方會突然失去函式/方法呼叫的線索。例如看某個函式的實現的時候會跳到乙個介面裡面去,那是因為這部分功能在執行期才會給乙個實現了這個介面的物件來進行具體的執行。從這個角度來說,設計模式也給我們研究**稍微帶來了一點小小的難度。在看linux下源**的時候也經常遇到這種問題,在這個時候尋找**線索比較好的方法是用乙個文字搜尋工具來搜尋相關的關鍵字。在linux下我經常會用grep,windows下面類似ultraedit的「批量檔案查詢」功能會很好用(或者「search and replace」之類的工具)。這個是我讀**的一點小小的經驗,如果你知道有更好的方法,請告訴我讓我也學習一下 ? 。

我不想大段大段的貼**出來佔地方(空間、頻寬,還有各位看官的注意力),在需要的地方我會貼上主要的**,因此最好能夠找**來對應著看。把**包解壓縮,我把它解到了「f:/sharpdevelop」(如果沒有說明,下文都是以此為**的根目錄了)。由於sharpdevelop本身對於察看**不是很方便,沒有「轉到定義」之類的功能,因此我建議你把它的**轉成vs的工程來看。不過很可惜,sharpdevelop的工程匯出功能現在有問題,如果匯出/src/sharpdevelop.cmbx 這個總的復合工程的話會失敗(我記得rc1版本是可以成功的,不知道為什麼後來的版本反而會出問題),所以只能乙個乙個工程的匯出。

好了,讓我們來看sharpdevelop的**吧。

1、小技巧的起點

在主程式的起點在/src/main/startup/sharpdevelopmain.cs,找到main函式這就是整個程式的起點了。開始的部分是顯示封面窗體並加上命令列控制,其中splashscreenform 定義在/src/main/base/gui/dialogs/splashscreen.cs檔案中,這部分我就不多說了。之後是

sharpdevelop為了有效的進行錯誤報告,因此自己進行了異常的控制。系統出現異常的時候,sharpdevelop會攔截下來彈出它自己的異常提示報告對話方塊。這個**就是在這一行實現的。其中 showerrorbox 這個方法就在類sharpdevelopmain中,exceptionbox 定義在/src/main/startup/dialogs/exceptionbox.cs中。如果需要進行自己的異常控制,可以學習一下這裡的技巧。

servicemanager.services.addservice(new messageservice());

servicemanager.services.addservice(new resourceservice());

servicemanager.services.addservice(new iconservice());

通過servicemanager(服務管理器)加入三個系統預設的服務,訊息服務、資源服務、圖示服務。這三個服務中,訊息服務是顯示各種資訊提示,另外兩個是屬於系統的資源,sharpdevelop通過服務來進行統一呼叫和管理。

servicemanager.services.initializeservicessubsystem("/workspace/services");

初始化其他的服務。sharpdevelop把服務定義在外掛程式樹的/workspace/services這個路徑中,凡是在這個路徑下的外掛程式都被認為是服務,因此如果你自己定義了乙個服務的話,也需要掛到這個路徑下(這裡就是系統服務的擴充套件點了)。

注意!這一步中,在我們的眼皮子底下悄悄的進行了乙個重要的初始化工作。各位看官請看,servicemanager 定義在/src/main/core/services/ servicemanager.cs檔案中,察看它的initializeservicessubsystem方法,我們發現這樣一行

addservices((iservice)addintreesingleton.addintree.gettreenode(servicespath).buildchilditems(this).toarray(typeof(iservice)));

在這裡,addintreesingleton首次呼叫了addintree(外掛程式樹)的例項。按照singleton模式,只有在首次呼叫的時候才會初始化例項,這裡也是同樣如此。整個系統的addintree是在這一步中進行了初始化工作,稍候我們將詳細介紹addintree如何進行初始化工作,先順便看看服務的初始化。在servicemanager的initializeservicessubsystem方法中,通過addintree檢索服務外掛程式路徑下的所有配置,並通過它來讀取、建立具體的物件,然後加入到服務列表中。之後通過乙個迴圈,逐個的呼叫各個服務的initializeservice方法初始化服務。

addintree的初始化工作容我們稍候再看,先把主體的**看完。

commands = addintreesingleton.addintree.gettreenode("/workspace/autostart").buildchilditems(null);

for (int i = 0; i < commands.count - 1; ++i)

/workspace/autostart是系統自動執行命令的擴充套件點路徑,定義在這個路徑下的外掛程式會在系統啟動的時候自動執行。在這裡,通過外掛程式樹初始化建立處於這個路徑下的command(命令),並逐一執行。buildchilditems方法的功能是建立這個擴充套件點下的command列表,我會在介紹addtree的時候具體說明它的實現。

主程式**的最後,初始化完畢、關閉封面窗體,然後執行命令列表中最後乙個命令(也就是系統的主介面)。在主介面退出的時候,系統解除安裝所有的服務。

在這部分**中,我們知道了兩個系統指定的擴充套件點路徑 /workspace/services 和 /workspace/autostart ,我們實現服務和指定系統自動執行命令的時候就可以掛到這兩個擴充套件點路徑下了。

託反射的福,servicemanager.services可以通過型別(介面)來查詢具體的例項,也就是getservices方法。但是servicemanager的具體實現我們可以容後再看,這裡已經不是最緊要的部分了。

接下來,我們來看看整個外掛程式系統的核心-addintree的**,看看它是如何通過外掛程式配置進行初始化並建立起整個系統的外掛程式樹骨幹。

SharpDevelop原始碼分析 二 頭緒

servicemanager.services.addservice new messageservice servicemanager.services.addservice new resourceservice servicemanager.services.addservice new ic...

SharpDevelop原始碼分析 二 頭緒

在大學課程裡面,我對於模擬電路總是搞不清楚,直到現在也是這樣。我總覺得電路圖很奇怪,總會問 這部分電路是做什麼用的 為什麼會有這樣的效果 在我的腦海裡面,每部分的電路都應該有一定的用處,可是我總是看不明白。我媽媽說,我的思路被軟體所固化的太久了,看電路圖不應該總是乙個個模組的看,正確的方法應該是從電...

《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具

檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...