天天看點

對MarshalByRefObject的解釋

今天看到一段介紹c#實作代理模式的代碼,使用到了marshalbyrefobject。那麼marshalbyrefobject到底是什麼東西呢?簡單來講,繼承此類的對象可以跨越應用程式域邊界被引用,甚至被遠端引用。遠端調用時,将産生一個遠端對象在本地的透明代理,通過此代理來進行遠端調用。一篇很好的解釋文章,來自http://dudu.cnblogs.com/archive/2004/03/04/2182.html

<b>問:</b><b></b>

<b></b>

打擾一下,請問marshalbyrefobject中的"marshal"應該怎樣了解?

<b>回複</b>:

按照package的意思了解——當一個對象需要長途跋涉到另一個環境中時,需要将其marshal成一個可以傳輸的形态(比如在.net remoting中對象将被打包成一個serializable的objref執行個體——這個byref就是指objref這種形态);同理,當打包以後傳輸到目标地點,還要執行unmarshal的操作将其還原為記憶體中的對象。:)

<b>問:</b>

謝謝!

marshalbyrefobject是不是可以這樣了解:對被引用的對象進行marshal。如果按照package的意思了解,那package的過程是怎樣的?

<b>msdn</b><b>上這樣講:</b>

<b>marshalbyrefobject</b>是通過使用代理交換消息來跨應用程式域邊界進行通訊的對象的基類.

<b>marshalbyrefobject</b>對象在本地應用程式域的邊界内可直接通路。遠端應用程式域中的應用程式首次通路<b>marshalbyrefobject</b>時,會向該遠端應用程式傳遞代理。對該代理後面的調用将封送回駐留在本地應用程式域中的對象。

在marshal中,上面所說的代理是什麼?有什麼用?

<b>msdn</b><b>上還講到:</b>

當跨應用程式域邊界使用類型時,類型必須是從<b>marshalbyrefobject</b>繼承的,而且由于對象的成員在建立它們的應用程式域之外無法使用,是以不得複制對象的狀态。

既然對象的狀态不能傳遞過去,那傳遞這個對象又有何意義?

第一次去了解marshalbyrefobject,有的問題可能提的比較膚淺,請您指點。

<b>回複:</b>

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)為本地的對象,并獲得其透明代理,然後就可以把方法調用消息在轉換回基于堆棧的調用發送給這個對象。

對象是在本地維護的,但是方法可以在遠端調用。你比如說一個web應用程式,你是通過本地的浏覽器遠端通路這個應用程式,但是應用程式的狀态不會由你的浏覽器負責(是以你隻是在通路這個應用程式提供給你的功能而已,你并沒于擁有應用程式本身,包括其所有資料),你隻是發送一個個的請求,伺服器告訴你處理的結果。在remoting中 也是一樣,當你獲得一個遠端對象的時候,你實際上隻擁有對這個對象的一個遠端引用,雖然你可以調用它的方法,但實際上這些操作都是發生在遠端的(就是前面 講過的過程),你隻是傳入了一些參數,得到了一個結果,但對象的狀态還是在遠端維護的(換句話說,對象本身也就是對象的所有狀态并沒有被往返傳遞,傳遞的 隻是傳入傳出的參數——當然,如果參數是一個mbro的話,還是傳遞對象被封送的引用)。 

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

我這樣的了解對不對?

一般的對象與從marshalbyrefobject繼承的對象差別是:

一般的對象隻能在本地應用程式域之内被引用,而marshalbyrefobject對象可以跨越應用程式域邊界被引用,甚至被遠端引用。

exactly! 當對象跨出appdomain邊界的時候,實際上隻是它的一個引用(objref)。你比如說吧:

public class localobject

{

  public void callremoteobject(marshalbyrefobject mbro)

  {

    console.writeline(mbro.tostring());

  }

}

當傳入一個在本地建立的mbro對象時,tostring()方法是直接發送給對象的;而當mbro是通過remoting建立的遠端對象的話,實際上它隻是一個包含有已經marshal好的objref的透明代理,objref裡面有什麼?對象執行個體的uri!是以當你調用這個遠端對象時,相當于向這個遠端端口(tcp://remoteserver/xxxx.rem)發送方法調用消息而已。隻不過透明代理隐藏了對象位置的概念,而remotingproxy真實代理則是實際上處理遠端方法調用和對象封送的中樞對象。

文章轉自莊周夢蝶  ,原文釋出時間5.17