国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

事件模式與觀察者模式

2019-11-08 02:39:50
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友



學(xué)習(xí)C#的事件模式時(shí)Delegate和event這二個(gè)概念比較難理解,因?yàn)檫@二個(gè)都被設(shè)計(jì)成關(guān)鍵字,想進(jìn)一步查看其定義和實(shí)現(xiàn)就沒(méi)有下文了,不過(guò)再難也得硬著頭皮弄明白,我以前好長(zhǎng)時(shí)間都是似懂非懂的狀態(tài),后來(lái)在學(xué)習(xí)了觀察者設(shè)計(jì)模式和IL后利用這二者的知識(shí)來(lái)理解就比較容易。下面我就用觀察者設(shè)計(jì)模式和IL來(lái)分析一下事件模式中Delegate和event這二個(gè)關(guān)鍵字。

        首先,我們來(lái)了解一下delegate究竟是什么東西,先來(lái)看一下下面的程序(為了演示,代碼盡量簡(jiǎn)略)。

       Using System;

public class Test

{

           public delegatevoid aaa();

            public static void Main(String[]args) {      

                     aaaa=new aaa(show);

                     a();

          }

        

           public static voidshow()

           {

                     Console.WriteLine("hi");

           }

}

        以上代碼用csc.exe編譯后再用ILDASM反編譯成文本文件:

.class public auto ansibeforefieldinit Test  extends [mscorlib]System.Object

{

 .class auto ansisealed nestedpublicaaa  extends[mscorlib]System.MulticastDelegate

 {

   .method public hidebysig specialnamertspecialname  instance void .ctor(object 'object', native int'method') runtime managed

   {

   } // end of method aaa::.ctor

   .method public hidebysig newslotvirtual instance void Invoke() runtime managed

   {

   } //end of method aaa::Invoke

 

   .method public hidebysig newslotvirtual instance class[mscorlib]System.IAsyncResult  BeginInvoke(class [mscorlib]System.AsyncCallback callback,

                       object 'object')runtime managed

   {

   } // end of method aaa::BeginInvoke

 

   .method public hidebysig newslotvirtual instance void EndInvoke(class [mscorlib]System.IAsyncResultresult) runtime managed

   {

   } // end of method aaa::EndInvoke

 

 } // end of class aaa

 

 .method public hidebysig static void Main(string[] args) cil managed

 {

   .entrypoint

   //

   .maxstack 2

   .locals init (class Test/aaa V_0)

   IL_0000: nop

IL_0001: ldnull

//將show方法的指針推送到計(jì)算堆棧上

   IL_0002: ldftn     void Test::show()

   IL_0008: newobj    instance voidTest/aaa::.ctor(object,

                                                      native int)

   IL_000d: stloc.0

   IL_000e: ldloc.0

   IL_000f: callvirt  instance voidTest/aaa::Invoke()

   IL_0014: nop

   IL_0015: ret

 } // end of method Test::Main

 

 .method public hidebysig static void show() cil managed

 {

   //

   .maxstack 8

   IL_0000: nop

   IL_0001: ldstr     "hi"

   IL_0006: call      void[mscorlib]System.Console::WriteLine(string)

   IL_000b: nop

   IL_000c: ret

 } // end of method Test::show

 

 .method public hidebysig specialnamertspecialname

         instance void .ctor() cil managed

 {

   //

   .maxstack 8

   IL_0000: ldarg.0

   IL_0001: call      instance void[mscorlib]System.Object::.ctor()

   IL_0006: ret

 } // end of method Test::.ctor

 

} // end of class Test

 

        從反編譯出來(lái)IL指令中可以看到delegate關(guān)鍵字修飾的aaa由編譯器轉(zhuǎn)換為一個(gè)繼承自System.MulticastDelegate的類,然后在main方法中以方法show的指針作參數(shù)構(gòu)造一個(gè)aaa的實(shí)例,后面再通過(guò)該實(shí)例調(diào)用Invoke方法,相信至此對(duì)delegate關(guān)鍵字應(yīng)該明白其作用了。

要了解事件模式的話,光是了解delegate還不夠,我們還得看看event是什么玩藝:

using System;

 

public class Test {

    public static voidMain(String[] args) {      

                  EventTest et = newEventTest();

           et.OnPRopertyChanged+=show;

                   et.Age=2;

    }

         public static void show()

         {

                 Console.WriteLine("event trigged");

         }       

}

 

  public class EventTest

  {     

         public delegate voidPropertyChangedHandler();

         public eventPropertyChangedHandler OnPropertyChanged;

          

         private int age;

        public int Age

        {

             get { return age; }

             set

                           {

                            age = value;

                                     if(OnPropertyChanged!=null)

                                     {

                                              OnPropertyChanged();

                                     }

                            }

       }

  }

 

學(xué)過(guò)MVVM模式的朋友對(duì)以上代碼是否有似曾相識(shí)的感覺(jué),用csc.exe編譯后再用ILDASM反編譯成文本文件:

.class public auto ansi beforefieldinit Test extends[mscorlib]System.Object

{

 .method public hidebysig staticvoid Main(string[] args) cil managed

 {

   .entrypoint

   //

   .maxstack 3

   .locals init (class EventTestV_0)

   IL_0000: nop

   IL_0001: newobj    instance voidEventTest::.ctor()

   IL_0006: stloc.0

   IL_0007: ldloc.0

   IL_0008: ldnull

   IL_0009: ldftn     void Test::show()

   IL_000f: newobj    instance void EventTest/PropertyChangedHandler::.ctor(object,native int)

   IL_0014: callvirt  instance void EventTest::add_OnPropertyChanged(classEventTest/PropertyChangedHandler)

   IL_0019: nop

   IL_001a: ldloc.0

   IL_001b: ldc.i4.2

   IL_001c: callvirt  instance void EventTest::set_Age(int32)

   IL_0021: nop

   IL_0022: ret

 } // end of method Test::Main

 

 .method public hidebysig staticvoid show() cil managed

 {

   //

   .maxstack 8

   IL_0000: nop

   IL_0001: ldstr     "event trigged"

   IL_0006: call      void [mscorlib]System.Console::WriteLine(string)

   IL_000b: nop

   IL_000c: ret

 } // end of method Test::show

 

 .method public hidebysigspecialname rtspecialname instancevoid .ctor() cil managed

 {

   //

   .maxstack 8

   IL_0000: ldarg.0

   IL_0001: call      instance void [mscorlib]System.Object::.ctor()

   IL_0006: ret

 } // end of method Test::.ctor

 

} // end of class Test

 

.class public auto ansi beforefieldinitEventTest extends [mscorlib]System.Object

{

 .class auto ansi sealed nestedpublic PropertyChangedHandler extends[mscorlib]System.MulticastDelegate

 {

   .method public hidebysigspecialname rtspecialname instancevoid .ctor(object 'object',  native int 'method') runtime managed

   {

   } // end of methodPropertyChangedHandler::.ctor

 

   .method public hidebysig newslotvirtual  instance void Invoke() runtime managed

   {

   } // end of methodPropertyChangedHandler::Invoke

 

   .method public hidebysig newslotvirtual instance class[mscorlib]System.IAsyncResult

           BeginInvoke(class[mscorlib]System.AsyncCallback callback, object 'object') runtime managed

   {

   } // end of methodPropertyChangedHandler::BeginInvoke

 

   .method public hidebysig newslotvirtual instance void EndInvoke(class [mscorlib]System.IAsyncResultresult) runtime managed

   {

   } // end of methodPropertyChangedHandler::EndInvoke

 

 } // end of classPropertyChangedHandler

 

 .field private classEventTest/PropertyChangedHandlerOnPropertyChanged

 .field private int32 age

 .method public hidebysigspecialname instance void add_OnPropertyChanged(classEventTest/PropertyChangedHandler 'value') cil managed

 {

   //

   .maxstack 3

   .locals init (classEventTest/PropertyChangedHandler V_0,

            classEventTest/PropertyChangedHandler V_1,

            classEventTest/PropertyChangedHandler V_2,

            bool V_3)

   IL_0000: ldarg.0

   IL_0001: ldfld     class EventTest/PropertyChangedHandler EventTest::OnPropertyChanged

   IL_0006: stloc.0

   IL_0007: ldloc.0

   IL_0008: stloc.1

   IL_0009: ldloc.1

   IL_000a: ldarg.1

   IL_000b: call      class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class[mscorlib]System.Delegate,

                                                                                           class [mscorlib]System.Delegate)

   IL_0010: castclass EventTest/PropertyChangedHandler

   IL_0015: stloc.2

   IL_0016: ldarg.0

   IL_0017: ldflda    class EventTest/PropertyChangedHandler EventTest::OnPropertyChanged

   IL_001c: ldloc.2

   IL_001d: ldloc.1

   IL_001e: call      !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<classEventTest/PropertyChangedHandler>(!!0&, !!0,  !!0)

   IL_0023: stloc.0

   IL_0024: ldloc.0

   IL_0025: ldloc.1

   IL_0026: ceq

   IL_0028: ldc.i4.0

   IL_0029: ceq

   IL_002b: stloc.3

   IL_002c: ldloc.3

   IL_002d: brtrue.s  IL_0007

 

   IL_002f: ret

 } // end of methodEventTest::add_OnPropertyChanged

 

 .method public hidebysigspecialname instance void

         remove_OnPropertyChanged(classEventTest/PropertyChangedHandler 'value') cil managed

 {

   //

   .maxstack 3

   .locals init (classEventTest/PropertyChangedHandler V_0,

            classEventTest/PropertyChangedHandler V_1,

            classEventTest/PropertyChangedHandler V_2,

            bool V_3)

   IL_0000: ldarg.0

   IL_0001: ldfld     class EventTest/PropertyChangedHandler EventTest::OnPropertyChanged

   IL_0006: stloc.0

   IL_0007: ldloc.0

   IL_0008: stloc.1

   IL_0009: ldloc.1

   IL_000a: ldarg.1

   IL_000b: call      class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,

                                                                                          class [mscorlib]System.Delegate)

   IL_0010: castclass EventTest/PropertyChangedHandler

   IL_0015: stloc.2

   IL_0016: ldarg.0

   IL_0017: ldflda    class EventTest/PropertyChangedHandler EventTest::OnPropertyChanged

   IL_001c: ldloc.2

   IL_001d: ldloc.1

   IL_001e: call      !!0 [mscorlib]System.Threading.Interlocked::CompareExchange<classEventTest/PropertyChangedHandler>(!!0, !!0, !!0)

   IL_0023: stloc.0

   IL_0024: ldloc.0

   IL_0025: ldloc.1

   IL_0026: ceq

   IL_0028: ldc.i4.0

   IL_0029: ceq

   IL_002b: stloc.3

   IL_002c: ldloc.3

   IL_002d: brtrue.s  IL_0007

 

   IL_002f: ret

 } // end of methodEventTest::remove_OnPropertyChanged

 

 .method public hidebysigspecialname instance int32  get_Age() cil managed

 {

   //

   .maxstack 1

   .locals init (int32 V_0)

   IL_0000: nop

   IL_0001: ldarg.0

   IL_0002: ldfld     int32 EventTest::age

   IL_0007: stloc.0

   IL_0008: br.s      IL_000a

 

   IL_000a: ldloc.0

   IL_000b: ret

 } // end of methodEventTest::get_Age

 

 .method public hidebysigspecialname instance void set_Age(int32'value') cil managed

 {

   //

   .maxstack 2

   .locals init (bool V_0)

   IL_0000: nop

   IL_0001: ldarg.0

   IL_0002: ldarg.1

   IL_0003: stfld     int32 EventTest::age

   IL_0008: ldarg.0

   IL_0009: ldfld     class EventTest/PropertyChangedHandlerEventTest::OnPropertyChanged

   IL_000e: ldnull

   IL_000f: ceq

   IL_0011: stloc.0

   IL_0012: ldloc.0

   IL_0013: brtrue.s  IL_0023

 

   IL_0015: nop

   IL_0016: ldarg.0

   IL_0017: ldfld     class EventTest/PropertyChangedHandler EventTest::OnPropertyChanged

   IL_001c: callvirt  instance void EventTest/PropertyChangedHandler::Invoke()

   IL_0021: nop

   IL_0022: nop

   IL_0023: ret

 } // end of methodEventTest::set_Age

 

 .method public hidebysigspecialname rtspecialname instance void .ctor() cil managed

 {

   //

   .maxstack 8

   IL_0000: ldarg.0

   IL_0001: call      instance void [mscorlib]System.Object::.ctor()

   IL_0006: ret

 } // end of methodEventTest::.ctor

 

 .eventEventTest/PropertyChangedHandler OnPropertyChanged

 {

   .addon instancevoid EventTest::add_OnPropertyChanged(class EventTest/PropertyChangedHandler)

   .removeoninstance void EventTest::remove_OnPropertyChanged(classEventTest/PropertyChangedHandler)

 } // end of eventEventTest::OnPropertyChanged

 .property instance int32 Age()

 {

   .get instance int32EventTest::get_Age()

   .set instance voidEventTest::set_Age(int32)

 } // end of propertyEventTest::Age

} // end of class EventTest

 

用event聲明事件后編譯器在編譯時(shí)給類中加了二個(gè)方法:

add_OnPropertyChanged(class EventTest/PropertyChangedHandler 'value')、

remove _OnPropertyChanged(class EventTest/PropertyChangedHandler 'value')。

在這二個(gè)方法中有二個(gè)調(diào)用:

System.Delegate::Combine(class [mscorlib]System.Delegate, class[mscorlib]System.Delegate)、

System.Delegate::Remove(class[mscorlib]System.Delegate, class[mscorlib]System.Delegate),

查一下MSDN這二個(gè)調(diào)用是干什么的:

Combine方法將兩個(gè)委托的調(diào)用列表連接在一起,Remove方法從一個(gè)委托的調(diào)用列表中移除另一個(gè)委托的最后一個(gè)調(diào)用列表。

委托里有個(gè)調(diào)用列表!

挖到這里,學(xué)過(guò)觀察者模式的朋友是否有似曾相識(shí)的感覺(jué):觀察者模式中被觀察者也有一個(gè)訂閱者列表,有Add和Remove方法。事件模式不就是觀察者模式嗎?,不過(guò)在C#中用delegate來(lái)實(shí)現(xiàn)觀察者模式中的更新狀態(tài)的接口和訂閱者列表,用event關(guān)鍵字實(shí)現(xiàn)的訂閱者的添加和刪除。

   理解了事件模式和觀察者模式的關(guān)系,對(duì)MVVM模式中的Notification類也就不難理解了。

 




發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 望都县| 大关县| 楚雄市| 崇州市| 闸北区| 文成县| 繁峙县| 将乐县| 广汉市| 锦屏县| 深州市| 依安县| 龙口市| 龙口市| 深泽县| 苍山县| 丰城市| 金华市| 桦川县| 田林县| 盱眙县| 花莲县| 三穗县| 游戏| 甘肃省| 胶南市| 乌海市| 绩溪县| 白银市| 锡林浩特市| 周至县| 枣强县| 新竹县| 沽源县| 富蕴县| 横山县| 武冈市| 灯塔市| 汉阴县| 峨山| 湛江市|