C# 是一個簡單的、現代的、通用的、面向對象的程式語言,它是由微軟(Microsoft)開發的
C#方法調度 有時,一些做的事情,就是為了看看他們將如何工作了。 主要的問題是,通過創建子類逐步建立特定的事件處理能力的系統。
基本介紹
- 中文名:C#技術書籍
- 外文名:C# Programming Guide
C#方法調度 有時,我們一些做的事情,就是為了看看他們將如何工作了。 我最近有一個情況,建設系統在C#中,我想多派(雙調度,尤其是),所以我張貼這證明我如何取得的希望,這將有利於他人的,或者我的系統工作其他人可以點出一個最好的解決方案,顯然我在興奮錯過嘗試一些我從來沒有做過。
主要的問題是,我想通過創建子類逐步建立特定的事件處理能力的系統。 隨著新的事件被添加到系統中,創建一個新的子類可以存儲任何有關國家和實施有關的事件的處理程式。 這可以一般地被看作是一個狀態機的制定,其中子類狀態,所發生的事件,因為我已經叫他們,啟動狀態轉換。 所以,我有一個參考對象在運行時這些國家之一 - 引用一個由一類是所有國家共同的祖先類 - 我要用於處理特定類型的事件定義我的一些工廠的機制。 事件對象的當前狀態我想處理的是同樣由一個由一類是我的所有事件的子類定義了一個共同的祖先類型的變數引用。 那么,現在的問題是,編譯器,使用靜態類型信息,永遠只能調用基類的事件處理程式的狀態。 製作這種方法將允許一個虛擬的呼叫方的運行時類型的決議,這樣我可以與一個特定的重載簽名的處理方法。 但是,這將意味著,我的基類需要定義每個事件類型的虛擬處理器,並且像一個大的頸部疼痛的聲音。 一方面,系統不涉及超載一個虛擬方法不能做我需要在所有(自定義處理程式在調用子類中定義的沒有),但是,另一方面,已經存在內置在回退功能的支持。 我想保留的基態類的處理方法將被調用的行為,如果沒有更具體的處理程式由國家對象的類型實現。
雙調度 我真的想在這個時候發生是有一個看起來像這樣的代碼行
currentState.Handle(currentEvent);
該調用最類型特定的Handle方法,可能由於該類型的currentState對象和類型的currentEvent對象。 這種行為被稱為多重調度,這對比的方式是最面向對象語言的工作。 典型的方法在面向對象語言的調用語法處於一個非常特殊的句法位置的方法的參數之一:前點。 例如,調用foo.bar();查找該bar方法定義類型的foo 。 但是值得注意的是foo ,在這裡,實際上是對一些參數執行bar的方法,即使它是不寫的原始碼的方式。
這種行為 - 單調度 - 在這種情況下是不足夠的。 我要通過使用代碼看起來像這樣我的方法的參數:
BaseState currentState;
...
BaseEvent currentEvent = GetEvent();
currentState.Handle(currentEvent);
我需要的是雙調度,和事實,即C#不提供這不應該是一個障礙。 當然,我們可以建立一個大的條件語句,看起來在參數類型,然後算出從那裡做什麼,但會令大家誰在方案看起來生病了。 不僅將一個報表一堆醜陋的條件是,這將意味著我們將不得不更新基類的Handle方法,我們每次添加一個事件類型。 這是瘋了! 因此,這裡的另一種方法。
其基本思想是,基類的Handle方法應反映在其自己的類型來尋找Handle方法,它定義。 當這個對象上,從基類派生的情況,我們會發現“超載”的子類(注意定義的方法:這不是嚴格來說,最重要的,但它是,直觀,超載的方法名)。 我們可以看看所有的版本的Handle方法,並挑選一個需要參數的基類方法相同的該類型作為參數傳遞給。 如果沒有匹配存在,基類可以提供一些備用的功能(也許只是提出一個錯誤,描述發生了什麼)。
使我們得到一個簡單的形式派遣多,但它確實涉及了在每個方法調用的類型反映。 幸運的是,我們可以加快,截至1位非常容易。 在一個基類的靜態構造函式,我們可以反映在所有的大會(類型注意,您可以這樣做,當一個程式集載入,如果你想要一個更具活力的外掛程式體系結構),挑選出那些從我們的基地state派生類。 然後,我們可以找到所有的Handle在這些類的方法,例如他們和存儲在哈希表進行檢查時,將基類的Handle方法被調用。 現在,我們可以添加狀態類處理某些事件,但對事件的處理沒有明確的類型,調速功能,而不必更改任何代碼任何地方!
在這裡,我們看到從基類的靜態構造函式的代碼。 它認為所有大會的有關類型,快取為每個方法的信息。
派遣= 新詞典<Int64, MethodInfo>(); 的
foreach(在 Assembly.GetCallingAssembly類型噸()。GetTypes())
( 如果(t.IsSubclassOf(typeof運算 (MyBase)))
( 的foreach(宓的 t.GetMethods的MethodInfo())
( 如果 (ss ==“處理”) ( ParameterInfo [] = mi.GetParameters標準桿();
如果 (pars.Length == 1)
( Int64碼=((Int64)t.GetHashCode()<<32)+ 標準桿[0]。
ParameterType.GetHashCode(); dispatch.Add(代碼,英里); )
)
)
)
/ /這是一個神奇的方法,我們要根據超負荷運行時類型。 公共虛擬無效句柄( 對象O) ( Int64值=((Int64) 這一點 。GetType()。GetHashCode()<<32)+ o.GetType()。GetHashCode(); 如果 (dispatch.ContainsKey(哈希)) ( 派遣[哈希]。調用( 這一點 , 新的 對象 [](Ø)); ) 其他 ( / /這是我們的回退功能 Console.WriteLine(“處理對象”+ o.ToString()); ) ) 我試圖讓事情簡單,你基本上可以放入任何基類的靜態構造函式的代碼,只是改變了該方法的名字你想調用雙調度。 通過保持自己的狀態類的檔案,你可以保持一個高度模組化的項目,使多個開發人員可以添加從來沒有甚至不必編輯同一檔案的新子類的系統。