莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          對MarshalByRefObject的解釋

          Posted on 2007-03-28 17:55 dennis 閱讀(11574) 評論(1)  編輯  收藏 所屬分類: C#歷程
          ??? 今天看到一段介紹C#實現(xiàn)代理模式的代碼,使用到了MarshalByRefObject。那么MarshalByRefObject到底是什么東西呢?簡單來講,繼承此類的對象可以跨越應用程序域邊界被引用,甚至被遠程引用。遠程調用時,將產生一個遠程對象在本地的透明代理,通過此代理來進行遠程調用。一篇很好的解釋文章,來自http://dudu.cnblogs.com/archive/2004/03/04/2182.html


          問:

          打擾一下,請問MarshalByRefObject中的"Marshal"應該怎樣理解?

          ?

          回復

          按照package的意思理解——當一個對象需要長途跋涉到另一個環(huán)境中時,需要將其marshal成一個可以傳輸?shù)男螒B(tài)(比如在.NET Remoting中對象將被打包成一個serializableObjRef實例——這個ByRef就是指ObjRef這種形態(tài));同理,當打包以后傳輸?shù)侥繕说攸c,還要執(zhí)行unmarshal的操作將其還原為內存中的對象。:)

          ?

          問:

          謝謝!

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

          ?

          MSDN上這樣講:

          MarshalByRefObject是通過使用代理交換消息來跨應用程序域邊界進行通訊的對象的基類.

          MarshalByRefObject對象在本地應用程序域的邊界內可直接訪問。遠程應用程序域中的應用程序首次訪問MarshalByRefObject時,會向該遠程應用程序傳遞代理。對該代理后面的調用將封送回駐留在本地應用程序域中的對象。

          ?

          Marshal中,上面所說的代理是什么?有什么用?

          ?

          MSDN上還講到:

          當跨應用程序域邊界使用類型時,類型必須是從MarshalByRefObject繼承的,而且由于對象的成員在創(chuàng)建它們的應用程序域之外無法使用,所以不得復制對象的狀態(tài)

          ?

          既然對象的狀態(tài)不能傳遞過去,那傳遞這個對象又有何意義?

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

          ?

          回復:

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

          ?

          對象是在本地維護的,但是方法可以在遠程調用。你比如說一個web應用程序,你是通過本地的瀏覽器遠程訪問這個應用程序,但是應用程序的狀態(tài)不會由你的瀏覽器負責(所以你只是在訪問這個應用程序提供給你的功能而已,你并沒于擁有應用程序本身,包括其所有數(shù)據(jù)),你只是發(fā)送一個個的請求,服務器告訴你處理的結果。在Remoting中 也是一樣,當你獲得一個遠程對象的時候,你實際上只擁有對這個對象的一個遠程引用,雖然你可以調用它的方法,但實際上這些操作都是發(fā)生在遠程的(就是前面 講過的過程),你只是傳入了一些參數(shù),得到了一個結果,但對象的狀態(tài)還是在遠程維護的(換句話說,對象本身也就是對象的所有狀態(tài)并沒有被往返傳遞,傳遞的 只是傳入傳出的參數(shù)——當然,如果參數(shù)是一個MBRO的話,還是傳遞對象被封送的引用)。?

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

          ?

          問:

          我這樣的理解對不對?

          一般的對象與從MarshalByRefObject繼承的對象區(qū)別是:

          一般的對象只能在本地應用程序域之內被引用,而MarshalByRefObject對象可以跨越應用程序域邊界被引用,甚至被遠程引用。

          ?

          回復

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

          ?

          public class LocalObject
          {

          ? public void CallRemoteObject(MarshalByRefObject mbro)
          ? {
          ??? Console.WriteLine(mbro.ToString());

          ? }
          }

          ?

          當傳入一個在本地創(chuàng)建的mbro對象時,ToString()方法是直接發(fā)送給對象的;而當mbro是通過Remoting創(chuàng)建的遠程對象的話,實際上它只是一個包含有已經(jīng)marshal好的ObjRef的透明代理,ObjRef里面有什么?對象實例的URI!所以當你調用這個遠程對象時,相當于向這個遠程端口(tcp://remoteServer/xxxx.rem)發(fā)送方法調用消息而已。只不過透明代理隱藏了對象位置的概念,而RemotingProxy真實代理則是實際上處理遠程方法調用和對象封送的中樞對象。


          評論

          # re: 對MarshalByRefObject的解釋  回復  更多評論   

          2011-09-24 14:16 by tb
          恩 學習了
          主站蜘蛛池模板: 洛南县| 瑞安市| 肇庆市| 亳州市| 东乡族自治县| 中西区| 诏安县| 信阳市| 同德县| 锦州市| 嵊泗县| 陈巴尔虎旗| 屏边| 平安县| 巧家县| 金堂县| 泸州市| 芜湖县| 吕梁市| 金阳县| 即墨市| 前郭尔| 淳化县| 颍上县| 泾川县| 涟水县| 金川县| 松桃| 七台河市| 永胜县| 石河子市| 社旗县| 乐山市| 乌什县| 鄂伦春自治旗| 甘孜县| 郁南县| 富顺县| 江永县| 兴宁市| 贺州市|