日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
順暢的使用C#Actor:另一個(gè)解決方案

在前兩篇文章中,我們了解到Erlang中靈活的模式匹配,以及在C#甚至F#中會(huì)都遭遇的尷尬局面。那么現(xiàn)在就應(yīng)該來(lái)設(shè)計(jì)一個(gè)解決方案了,我們?nèi)绾尾拍茉贑#這樣的語(yǔ)言里順暢地使用Actor模型呢?不僅如此,***我們還能獲得其它一些優(yōu)勢(shì)。

創(chuàng)新互聯(lián)建站服務(wù)項(xiàng)目包括牧野網(wǎng)站建設(shè)、牧野網(wǎng)站制作、牧野網(wǎng)頁(yè)制作以及牧野網(wǎng)絡(luò)營(yíng)銷策劃等。多年來(lái),我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,牧野網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到牧野省份的部分城市,未來(lái)相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

C# Actor:“消息”、“協(xié)議”和“接口”
Actor模型中的對(duì)象如果要進(jìn)行交互,唯一的手段便是發(fā)送消息。不同語(yǔ)言/平臺(tái)上的消息有不同的表現(xiàn)形式,但是它們所傳遞的信息是一致的:
◆做什么事情
◆做這件事情需要的數(shù)據(jù)

例如,Erlang中往往會(huì)使用Tag Message的格式作為消息:

 
 
 
  1. {doSomething, Arg1, Arg2, Arg3, ...} 

其中,原子doSomthing表示“做什么”,而后面的ArgN便是一個(gè)個(gè)的參數(shù),使用Erlang中的模式匹配可以很方便地捕獲消息中的數(shù)據(jù)。在C#等語(yǔ)言中,由于并非專為了Actor模型設(shè)計(jì),因此一個(gè)Message往往只能是一個(gè)對(duì)象。但是這個(gè)對(duì)象的職責(zé)并沒(méi)有減輕,因此我們需要自己處理的事情就多了。我們可能會(huì)這樣做:

學(xué)Erlang的Tag Message,但是這樣會(huì)產(chǎn)生大量丑陋的類型轉(zhuǎn)換操作,并且喪失了靜態(tài)檢查功能。
為每種消息創(chuàng)建不同的Message類型,但是這樣會(huì)產(chǎn)生大量類類型,每個(gè)類型又有各種屬性,非常麻煩。
這兩種做法在上一篇文章里都有過(guò)討論,感興趣的朋友可以再去“回味”一番。那么,究竟什么是消息呢?根據(jù)我的理解,“消息”其實(shí)是這么一種東西:
◆“消息”表示“發(fā)送方”和“接受方”之間的“通信協(xié)議”(例如Erlang中的“模式”)。
◆“消息”表示“發(fā)送方”要“接受方”所做的事情,但是并沒(méi)有要求“接受方”需要怎么做。
◆一個(gè)Actor可能會(huì)會(huì)作為“接受方”遵守多種“通信協(xié)議”。

經(jīng)過(guò)這樣的描述,您是否覺(jué)得.NET中有一種東西和“消息”非常接近?沒(méi)錯(cuò),那就是“接口”,因?yàn)椋?br />◆“接口”從概念上講便是一種“協(xié)議”。
◆“接口”表示“能做什么”,但沒(méi)有限制“怎么做”。
◆一個(gè)Actor可以實(shí)現(xiàn)多個(gè)接口,即遵守多種協(xié)議。

看上去還真是一一對(duì)應(yīng)啊!那么我們?cè)賮?lái)深入一步進(jìn)行對(duì)比,“接口”能否傳遞消息所要表現(xiàn)的信息?答案也是肯定的:
◆做什么事情:接口中的一個(gè)方法。
◆需要的數(shù)據(jù):接口的參數(shù)。

也就是說(shuō),如之前的那條Erlang消息,在C#中便可以表示為:

 
 
 
  1. x.DoSomething(arg1, arg2, arg3, ...) 

基于這樣的類比,我們發(fā)現(xiàn)使用“接口”還可以帶來(lái)一個(gè)額外的東西,那就是“消息組”。如Erlang這樣語(yǔ)言,消息與消息之間是完全獨(dú)立的。.NET中的接口可以包含多個(gè)方法,這就是一種“分組”,我們可以利用這種方式來(lái)更好地管理有關(guān)聯(lián)的消息。此外,利用.NET中的訪問(wèn)限制符(public,internal等)還可以實(shí)現(xiàn)消息的公開和隱藏。而且因?yàn)榻涌诘膮?shù)是強(qiáng)類型的,所以可以得到編譯期的檢查,也可以享受編輯工具的代碼提示及重構(gòu)……C#編程里的種種優(yōu)勢(shì)似乎我們一個(gè)都沒(méi)有拉下。

C# Actor看似美好的實(shí)現(xiàn)
等一下,接口只是一種“協(xié)議”,但是“消息”還必須是一個(gè)實(shí)體,一個(gè)對(duì)象,并且“攜帶”了這個(gè)協(xié)議才能在Actor之間傳遞埃這個(gè)對(duì)象除了攜帶協(xié)議所需要的數(shù)據(jù)以外,還要能夠告訴接受方究竟該“操作什么”。“操作”帶上“數(shù)據(jù)”,于是我就想到了“委托”。例如,如果我們想要發(fā)送一個(gè)“協(xié)議”,叫做IDoHandler,那么我們便可以構(gòu)造一個(gè)Action﹤IDoHandler>對(duì)象——這正是Lambda表達(dá)式的用武之地:

 
 
 
  1. Action﹤IDoHandler> m = x => x.Do(0, 1, 2, ...); 

好,那么我們還是用乒乓測(cè)試來(lái)嘗試一番。我們知道,乒乓測(cè)試會(huì)讓Ping對(duì)象和Pong對(duì)象相互發(fā)送消息,我們各使用一個(gè)“消息組”,也就是“接口”來(lái)定義消息:

 
 
 
  1. public interface IPongMessageHandler { }  
  2.  
  3. public interface IPingMessageHandler { }  

那么,Ping和Pong兩個(gè)Actor類型又該如何定義呢?我們知道,Ping需要處理Pong發(fā)來(lái)的消息,因此它需要實(shí)現(xiàn)IPongMessageHandler接口,并且需要接受類型為Action﹤IPongMessageHandler>的消息。Pong與Ping類似,因此它們的定義為:

 
 
 
  1. public class Ping : Actor﹤Action﹤IPongMessageHandler>>, IPongMessageHandler  
  2. {  
  3.     private int m_count;  
  4.  
  5.     public Ping(int count)  
  6.     {  
  7.         this.m_count = count;  
  8.     }  
  9.  
  10.     protected override void Receive(Action﹤IPongMessageHandler> message)  
  11.     {  
  12.         message(this);  
  13.     }  
  14.  
  15.     ...  
  16. }  
  17.  
  18. public class Pong : Actor﹤Action﹤IPingMessageHandler>>, IPingMessageHandler  
  19. {  
  20.     protected override void Receive(Action﹤IPingMessageHandler> message)  
  21.     {  
  22.         message(this);  
  23.     }  
  24.  
  25.     ...  
  26. }  

從代碼上看,實(shí)際操作中我們并不需要讓Ping或Pong直接繼承Handler接口,只要最終提供一個(gè)對(duì)象給message執(zhí)行即可。嚴(yán)格說(shuō)來(lái),“接口”只是一個(gè)“消息組”,具體的“消息”還是要落實(shí)到接口中的方法。定義了Ping和Pong之后,我們便可以明確接口中的方法了(確切地說(shuō),是明確了方法的參數(shù)):

 
 
 
  1. public interface IPongMessageHandler  
  2. {  
  3.     void Pong(Pong pong);  
  4. }  
  5.  
  6. public interface IPingMessageHandler  
  7. {  
  8.     void Ping(Ping ping);  
  9.     void Finish();  
  10. }  

使用了接口,自然就要提供方法的實(shí)現(xiàn)了。我們先從典型而簡(jiǎn)單的Pong對(duì)象看起:

 
 
 
  1. public class Pong : Actor﹤Action﹤IPingMessageHandler>>, IPingMessageHandler  
  2. {  
  3.     ...  
  4.  
  5.     #region IPingMessageHandler Members  
  6.  
  7.     void IPingMessageHandler.Ping(Ping ping)  
  8.     {  
  9.         Console.WriteLine("Pong received ping");  
  10.         ping.Post(h => h.Pong(this));  
  11.     }  
  12.  
  13.     void IPingMessageHandler.Finish()  
  14.     {  
  15.         Console.WriteLine("Finished");  
  16.         this.Exit();  
  17.     }  
  18.  
  19.     #endregion  
  20. }  

原本需要在得到消息之后,根據(jù)消息的內(nèi)容作出不同的響應(yīng)。而現(xiàn)在,消息會(huì)被自動(dòng)轉(zhuǎn)發(fā)為接口中的方法調(diào)用,我們只需要實(shí)現(xiàn)特定的方法即可。在Ping方法中,我們會(huì)得到一個(gè)Ping類型的對(duì)象——于是我們?cè)傧蛩貜?fù)一個(gè)消息。消息的類型是Action﹤IPongMessageHandler>,可以看出,使用Lambda表達(dá)式構(gòu)造這樣一個(gè)消息特別方便。

Ping類也只需要實(shí)現(xiàn)IPongMessageHandler即可,只是這段邏輯“略顯復(fù)雜”:

 
 
 
  1. public class Ping : Actor﹤Action﹤IPongMessageHandler>>, IPongMessageHandler  
  2. {  
  3.     ...  
  4.  
  5.     public void Start(Pong pong)  
  6.     {  
  7.         pong.Post(h => h.Ping(this));  
  8.     }  
  9.  
  10.     #region IPongMessageHandler Members  
  11.  
  12.     void IPongMessageHandler.Pong(Pong pong)  
  13.     {  
  14.         Console.WriteLine("Ping received pong");  
  15.  
  16.         if (--this.m_count > 0)  
  17.         {  
  18.             pong.Post(h => h.Ping(this));  
  19.         }  
  20.         else 
  21.         {  
  22.             pong.Post(h => h.Finish());  
  23.             this.Exit();  
  24.         }  
  25.     }  
  26.  
  27.     #endregion  
  28. }  

收到Pong消息之后,將count減1,如果還大于0,則回復(fù)一個(gè)Ping消息,否則就回復(fù)一個(gè)Finish并退出。***啟動(dòng)乒乓測(cè)試:

new Ping(5).Start(new Pong());由于使用了接口作為消息的協(xié)議,因此無(wú)論是編輯器還是編譯器都可以給我們足夠的支持。同時(shí),對(duì)于消息的處理也無(wú)須如上一篇文章那樣不斷進(jìn)行判斷和類型轉(zhuǎn)換,代碼可謂流暢不少。

C# Actor致命的缺陷
雖說(shuō)沒(méi)有***的東西,但目前的缺陷卻是致命的。

在實(shí)際使用過(guò)程中,消息的“發(fā)送方”和消息的“接收方”應(yīng)該完全無(wú)關(guān),它們互不知道對(duì)方具體是誰(shuí),只應(yīng)該基于“協(xié)議”,也就是“接口”來(lái)實(shí)現(xiàn)??上г谏厦孢@段代碼中,很多東西都被“強(qiáng)橫”地限制住了。例如,Ping消息會(huì)附帶一個(gè)ping對(duì)象作為參數(shù),ping對(duì)象會(huì)等待一個(gè)Pong消息。但是,發(fā)送Ping消息(并等待Pong消息)的一方很可能是各種類型的Actor,不一定是Ping類型。有朋友可能會(huì)說(shuō),那么我們把IPingMessageHandler的Ping方法的簽名改成這樣,不就可以了嗎?

 
 
 
  1. void Ping(Actor﹤Action﹤IPongMessageHandler>> ping) 

是的,此時(shí)的ping,的確是在“等待Pong消息的Actor對(duì)象”。但是,這意味著ping對(duì)象它也只能是這個(gè)指明的Actor類型了。在實(shí)際使用過(guò)程中,這幾乎是不可能的事情。因?yàn)橐粋€(gè)Actor很可能會(huì)接受各種消息,它很難做到“一心一意”。因此這篇文章所提出的做法,幾乎只能滿足如乒乓測(cè)試這樣簡(jiǎn)單的Actor模型使用場(chǎng)景。我們必須改變。

改變的方式有不少,從“向弱類型妥協(xié)”到“利用.NET 4.0中的協(xié)變/逆變”,都可以滿足不同的場(chǎng)景——不過(guò)我們還是下次再說(shuō)吧。

F#的實(shí)現(xiàn)
本文描述的方式也可以運(yùn)用在在F#中。首先自然還是接口的定義:

 
 
 
  1. type IPingMessageHandler =  
  2.     abstract Ping : Ping -> unit  
  3.     abstract Finish : unit -> unit  
  4.  
  5. and IPongMessageHandler =   
  6.     abstract Pong : Pong -> unit  

以上便是F#中定義接口的方式,與C#相比更為簡(jiǎn)潔。接著便是Ping類型的實(shí)現(xiàn):

 
 
 
  1. and Ping() =  
  2.     inherit (IPongMessageHandler -> unit) Actor()  
  3.     let mutable count = 5  
  4.     override self.Receive(message) = message self  
  5.  
  6.     member self.Start(pong : Pong) =   
  7.         pong ﹤﹤ fun h -> self |> h.Ping  
  8.       
  9.     interface IPongMessageHandler with   
  10.         member self.Pong(pong) =  
  11.             printfn "Ping received pong" 
  12.             count ﹤- count - 1  
  13.             if (count > 0) then  
  14.                 pong ﹤﹤ fun h -> self |> h.Ping  
  15.             else 
  16.                 pong ﹤﹤ fun h -> h.Finish()  
  17.                 self.Exit()Pong類型的實(shí)現(xiàn)則更為簡(jiǎn)單:  
  18.  
  19. and Pong() =  
  20.     inherit (IPingMessageHandler -> unit) Actor()  
  21.     override self.Receive(message) = message self  
  22.       
  23.     interface IPingMessageHandler with  
  24.         member self.Ping(ping) =  
  25.             printfn "Pong received ping" 
  26.             ping ﹤﹤ fun h -> self |> h.Pong  
  27.           
  28.         member self.Finish() =  
  29.             printfn "Finished" 
  30.             self.Exit()啟動(dòng)乒乓測(cè)試:  
  31.  
  32. (new Pong()) |> (new Ping()).Start;  
  33.  

名稱欄目:順暢的使用C#Actor:另一個(gè)解決方案
網(wǎng)站路徑:http://www.5511xx.com/article/djdoedd.html