可遠端處理和不可遠端處理的物件
本主題專門說明一項為了在現有應用程式中提供回溯相容性而保留的舊有技術,不建議用於新的開發工作。分散式應用程式應使用 Windows Communication Foundation (WCF) 進行開發。
在應用程式定義域中建立的專屬物件可以直接由該定義域呼叫,而且從該定義域外使用該物件時,一定會發生一些狀況,這點請您要特別記住。並非每種型別的物件都可以有效率地跨定義域界限來發行或取用;因此,您必須依據應用程式的需求,決定要發行的物件型別。關於分散式應用程式,有兩種物件類別可供使用:不可遠端處理的物件與可遠端處理的物件。
不可遠端處理的物件
有些物件不能離開本身的應用程式定義域;由於它們並未宣告序列化 (Serialization) 的方法,因此永遠無法封送處理。這些不可遠端處理的物件主要是用在當初建立它們的相同應用程式定義域中,而且一律由該應用程式定義域來直接存取它們。大部分位於 .NET Framework 類別程式庫中的基底類別都是不可遠端處理的物件。不可遠端處理的物件不能複製到或表示於另一個應用程式定義域中。這些物件只能透過本身原始的應用程式定義域來存取。
可遠端處理的物件
可遠端處理的物件可以透過 Proxy 從所屬應用程式定義域或內容外部存取,或者加以複製並將這些複本傳遞至所屬應用程式定義域或內容外部;亦即,有些可遠端處理的物件會以傳址方式來傳遞,而有些則是透過數值來傳遞。
可遠端處理的物件即為可在四散的環境下運作良好的物件。可遠端處理的物件主要有兩種:
以傳值方式封送處理的物件,這些物件可以加以複製並從應用程式定義域中傳遞出去。
以傳址方式封送處理的物件,用戶端可透過針對該物件建立的 Proxy 來遠端存取物件。
以傳值方式封送處理的物件
以傳值方式封送處理 (MBV) 的物件會宣告本身的序列化規則 (藉由實作 ISerializable 來實作本身的序列化,或是使用 SerializableAttribute 標記,來告訴系統自動序列化物件),但是不會延伸 MarshalByRefObject。遠端系統會針對這些物件製作完整的複本,並將這些複本傳遞至呼叫的應用程式定義域中。一旦此複本位於呼叫端的應用程式定義域中時,對複本的呼叫會直接載入該複本中。此外,當成引數來傳遞的 MBV 物件也會以傳值方式來傳遞。除了宣告 SerializableAttribute 屬性或是實作 ISerializable 以外,您無須做任何動作以便跨應用程式或內容界限來傳遞類別的執行個體。
注意: |
---|
從 .NET Framework 1.1 版開始,遠端基礎結構不會自動還原序列化伺服器上的特定型別。如果您的應用程式嘗試傳遞不是自動序列化的型別,您必須先將伺服器的還原序列化 (Deserialization) 層級設為 Full ,這樣伺服器才能還原序列化並使用您的 MBV 物件。如需詳細資訊,請參閱 .NET 遠端處理中的自動還原序列化。 |
如果因為效能或處理因素而需要將物件的完整狀態以及任何可執行功能移至目標應用程式定義域中,請使用 MBV 物件。在許多情況下,這麼做可以降低在網路、處理序與應用程式定義域界限之間冗長且耗用資源的來回行程。MBV 物件同時可直接從物件的原始應用程式定義域中取用。在此情況下,由於未發生任何封送處理,因此不會製作任何複本,而且存取作業也會很有效率。
除非您正在延伸已經實作了 ISerializable 的類別,否則請使用 SerializableAttribute 來建立傳值封送處理的型別。在此情況下,您必須為您的型別實作 ISerializable。
遠端系統會延伸使用可序列化物件。另一個應用程式定義域中的物件參考 (藉由遠端系統之 ObjRef 類別來表示) 本身為可序列化;您可以完全加以複製,並將複本傳遞至用戶端。此外,傳輸資料的物件通常都是可序列化物件。例如,資料集可延伸 MarshalByValueComponent 以實作 ISerializable。
遠端使用者定義例外狀況
系統定義的例外狀況全部都是傳址封送處理的型別 (它們負責實作 ISerializable 介面)。當遠端物件擲回這些例外狀況時,就會在遠端基礎結構允許的情況下自動複製到呼叫端。從 .NET Framework 1.1 版開始,<customErrors> 項目必須設為 off 以讓例外狀況流向呼叫端。
如需如何建立可由遠端物件擲回並由遠端呼叫端捕捉的例外狀況型別之詳細資訊,請參閱 How To: Create an Exception Type That Can be Thrown by Remote Objects
以傳址方式封送處理的物件
以傳址方式封送處理 (MBR) 的物件,就是至少可延伸 System.MarshalByRefObject 的可遠端處理物件。當用戶端在本身應用程式定義域中建立 MBR 物件的執行個體時,.NET 遠端基礎結構會依據所宣告的啟動過程型別建立用來表示 MBR 物件的 Proxy,並將該 Proxy 的參考傳回呼叫端。接著,用戶端會呼叫 Proxy。.NET 遠端處理會封送處理遠端物件之應用程式定義域的呼叫,並叫用此呼叫。
注意: |
---|
如果用戶端與 MBR 物件都位於相同的應用程式定義域中,則基礎結構會將 MBR 物件的直接參考傳回用戶端,以避免對封送處理造成負荷。 |
如果將 System.MarshalByRefObject 當成參數來傳遞,則在呼叫抵達時它會變成另一個應用程式定義域中的 Proxy。MBR 會傳回值,而 out 參數也會比照辦理。
注意: |
---|
從 .NET Framework 1.1 版開始,.NET 遠端基礎結構不會自動還原序列化伺服器上的特定型別。例如,若要針對以參數形式來傳遞的 MBR 物件取得支援,您必須先將伺服器的還原序列化層級設為 Full ,伺服器才能還原序列化並使用 MBR 參數。如需詳細資訊,請參閱 .NET 遠端處理中的自動還原序列化。 |
當物件狀態與任何可執行功能都應保留在當初建立 MBR 物件的應用程式定義域中時,您應該使用 MBR 物件。例如,含有內部欄位 (作業系統控制代碼) 的物件應該延伸 System.MarshalByRefObject,否則在另一個應用程式定義域、另一個處理序,或是另一部電腦上的作業系統控制代碼將無意義。有時候物件大小也可能超乎想像地大;對於功能強大的伺服器來說也許不算什麼,但是當您透過線路傳送至 33.6 KBps 的數據機時就是一個大問題。
內容繫結物件
內容繫結物件就是繼承自 System.ContextBoundObject 的 MBR 物件,此物件本身又繼承自 System.MarshalByRefObject。您可以將內容想像成應用程式定義域的子區域,此區域會在執行期間為駐留在內的物件提供一個豐富的環境。例如,內容可以保證多個執行緒無法同時存取這些物件。每個應用程式定義域都有預設的內容。大部分 Managed 程式碼在建立物件之後,都會使用定義域的預設內容直接從相同的應用程式定義域中呼叫成員,而且不會產生與內容相關的問題。所有繼承自 System.ContextBoundObject 的型別都會當成 Proxy 公開給其他內容 (位於相同定義域或其他定義域中)。
例如,假設您的方法位於屬於交易一部分的型別上,因而當初建立此方法之內容的特定規則會繫結此方法。該型別應該是繼承自 System.ContextBoundObject,因此可由本身內容來存取該物件,而系統則可以針對與該物件及其方法相關聯的異動強制執行規則。如果從屬於相同應用程式定義域的另一個內容來呼叫 System.ContextBoundObject,則會建立呼叫端的 Proxy,但是內容之間的通訊不會經過通道系統 (在此情況下,這麼做可增加呼叫效率)。
由於跨越每個界限需要花費一些處理時間,您應該先決定物件必須跨越哪個界限,再決定伺服器應該成為哪種型別的可遠端處理物件。特定內容的特定物件只能透過該內容直接存取。特定應用程式定義域的特定物件也是如此。若要遠端處理任何一個物件,遠端系統必須先成功跨越內容界限、應用程式界限,或兩者同時跨越,才能從專屬於伺服器物件的任何一個界限中叫用該伺服器物件。如果您不需要進行內容檢查來呼叫物件,就不應該讓您的遠端型別延伸 System.ContextBoundObject;使用 System.MarshalByRefObject 會執行得更好。如果您需要進行內容檢查,就應該延伸 System.ContextBoundObject,但是您必須了解在對物件進行呼叫之前,必須先跨越額外的界限。
發行範圍
不同的遠端系統採用不同的方式來決定可遠端使用的成員與成員類型。.NET 遠端處理會將物件公開至其他應用程式定義域中 (如同它們是本機物件一樣),並產生下列例外狀況:
靜態成員
請勿遠端處理靜態欄位與方法,請透過直接記憶體來存取欄位。也就是說,.NET 遠端處理一律處理某種格式的執行個體成員。
執行個體欄位與存取子
針對執行個體欄位與存取子方法,系統會在執行階段插入檢查以判斷物件是否為 Proxy。如果不是 Proxy,則欄位將採取直接存取方式。否則,Proxy 將提供存取子供呼叫端使用。
私用方法
私用方法不可以遠端處理。您不能將委派包裝起來,然後從遠端傳遞至私有方法。
委派
委派就是以傳值方式封送處理的物件。委派中的物件可以是任何型別的可遠端處理物件,可序列化物件、MarshalByRefObject 物件或是 ContextBoundObject 物件。唯一的例外狀況就是,您無法成功遠端處理介面方法的委派。委派會包裝介面方法的實作,前提是伺服器必須具備可用的用戶端型別資訊。
覆寫 Object 上的方法
由於效能緣故,Object 上的虛擬方法一律在當初呼叫它們的應用程式定義域中以區域的方式執行。對下列任何一種方法的呼叫只有當遠端物件已經覆寫了這些方法時才會包含在遠端物件中。
Equals
這個虛擬方法會在被覆寫時從遠端執行。
GetHashCode
這個方法會在本機執行。
ToString
這個虛擬方法會在被覆寫時從遠端執行。
Equals (靜態版本)
這個方法會在本機執行。
MemberwiseClone
這個方法會在本機執行。