對MarshalByRefObject的解釋

dennis_zane發表於2007-03-28
    今天看到一段介紹C#實現代理模式的程式碼,使用到了MarshalByRefObject。那麼MarshalByRefObject到底是什麼東西呢?簡單來講,繼承此類的物件可以跨越應用程式域邊界被引用,甚至被遠端引用。遠端呼叫時,將產生一個遠端物件在本地的透明代理,通過此代理來進行遠端呼叫。一篇很好的解釋文章,來自http://dudu.cnblogs.com/archive/2004/03/04/2182.html


問:<o:p>

打擾一下,請問MarshalByRefObject中的"Marshal"應該怎樣理解?<o:p>

<o:p> </o:p>

回覆

按照package的意思理解——當一個物件需要長途跋涉到另一個環境中時,需要將其marshal成一個可以傳輸的形態(比如在.NET Remoting中物件將被打包成一個serializableObjRef例項——這個ByRef就是指ObjRef這種形態);同理,當打包以後傳輸到目標地點,還要執行unmarshal的操作將其還原為記憶體中的物件。:)<o:p>

<o:p> </o:p>

問:<o:p>

謝謝!<o:p>

MarshalByRefObject是不是可以這樣理解:對被引用的物件進行Marshal。如果按照package的意思理解,那package的過程是怎樣的?<o:p>

 <o:p>

MSDN上這樣講:<o:p>

MarshalByRefObject是通過使用代理交換訊息來跨應用程式域邊界進行通訊的物件的基類.<o:p>

MarshalByRefObject物件在本地應用程式域的邊界內可直接訪問。遠端應用程式域中的應用程式首次訪問MarshalByRefObject時,會向該遠端應用程式傳遞代理。對該代理後面的呼叫將封送回駐留在本地應用程式域中的物件。<o:p>

 <o:p>

Marshal中,上面所說的代理是什麼?有什麼用?<o:p>

 <o:p>

MSDN上還講到:<o:p>

當跨應用程式域邊界使用型別時,型別必須是從MarshalByRefObject繼承的,而且由於物件的成員在建立它們的應用程式域之外無法使用,所以不得複製物件的狀態<o:p>

 <o:p>

既然物件的狀態不能傳遞過去,那傳遞這個物件又有何意義?<o:p>

第一次去理解MarshalByRefObject,有的問題可能提的比較膚淺,請您指點。<o:p>

<o:p> </o:p>

回覆:<o:p>

MarshalByRefObject是所有可以在AppDomain邊界外部訪問的物件的基類,重心不是marshal,而是object,即object that could be marshaled by reference,也就是可以通過Ref(實際上是ObjRef物件)的機制進行封送MSDN中文版對marshal一詞的翻譯)的物件。封送的行為是由代理來做的,這裡說的代理就是我文章中講過的.NET Remoting的真實代理(即RemotingProxy)。真實代理不是有一個Invoke()方法嗎?當你透過對一個MBRO的透明代理訪問該物件的方法時,透明代理將把基於堆疊的方法呼叫轉換為方法呼叫訊息(IMethodCallMessage)並轉發給真實代理(在Remoting的場合中也即RemotingProxy),而RemotingProxy的任務就是把物件封送並連同方法呼叫訊息一起轉發給遠端應用程式域;到達目的地以後的操作類似:遠端應用程式域中的監聽方當收到發來的方法呼叫訊息時,先取出封送好的ObjRef(這個物件裡面儲存著發來呼叫的那個物件!),將其結封(unmarshal)為本地的物件,並獲得其透明代理,然後就可以把方法呼叫訊息在轉換回基於堆疊的呼叫傳送給這個物件。<o:p>

 <o:p>

物件是在本地維護的,但是方法可以在遠端呼叫。你比如說一個web應用程式,你是通過本地的瀏覽器遠端訪問這個應用程式,但是應用程式的狀態不會由你的瀏覽器負責(所以你只是在訪問這個應用程式提供給你的功能而已,你並沒於擁有應用程式本身,包括其所有資料),你只是傳送一個個的請求,伺服器告訴你處理的結果。在Remoting中 也是一樣,當你獲得一個遠端物件的時候,你實際上只擁有對這個物件的一個遠端引用,雖然你可以呼叫它的方法,但實際上這些操作都是發生在遠端的(就是前面 講過的過程),你只是傳入了一些引數,得到了一個結果,但物件的狀態還是在遠端維護的(換句話說,物件本身也就是物件的所有狀態並沒有被往返傳遞,傳遞的 只是傳入傳出的引數——當然,如果引數是一個MBRO的話,還是傳遞物件被封送的引用)。 <o:p>

也許應該給你準備一個好理解的例子……你就會豁然開朗了。:)<o:p>

<o:p> </o:p>

問:<o:p>

我這樣的理解對不對?<o:p>

一般的物件與從MarshalByRefObject繼承的物件區別是:<o:p>

一般的物件只能在本地應用程式域之內被引用,而MarshalByRefObject物件可以跨越應用程式域邊界被引用,甚至被遠端引用。<o:p>

<o:p> </o:p>

回覆

Exactly! 當物件跨出AppDomain邊界的時候,實際上只是它的一個引用(ObjRef)。你比如說吧:<o:p>

 <o:p>

public class LocalObject
{
<o:p>

  public void CallRemoteObject(MarshalByRefObject mbro)
  {
    Console.WriteLine(mbro.ToString());
<o:p>

  }
}
<o:p>

 <o:p>

當傳入一個在本地建立的mbro物件時,ToString()方法是直接傳送給物件的;而當mbro是通過Remoting建立的遠端物件的話,實際上它只是一個包含有已經marshal好的ObjRef的透明代理,ObjRef裡面有什麼?物件例項的URI!所以當你呼叫這個遠端物件時,相當於向這個遠端埠(tcp://remoteServer/xxxx.rem)傳送方法呼叫訊息而已。只不過透明代理隱藏了物件位置的概念,而RemotingProxy真實代理則是實際上處理遠端方法呼叫和物件封送的中樞物件。

107037.html

dennis 2007-03-28 17:55 發表評論

相關文章