• 【Emit基础】IL中发布、订阅、触发事件


         在下面的例子中,我定义了一个事件发布类Computer,事件订阅者ComputerManager。Computer发布了一个OnAction事件,并且该事件在Increase方法被调用时触发。ComputerManager接收到事件通知时,会将成员字段handleCount增加1.

         先看Computer的定义:

    .namespace ILTest
    {
        .
    class public auto ansi beforefieldinit Computer extends [mscorlib]System.Object
        {        
                  
          
       //事件对应的委托实例
            .field private class [ESBasic]ESBasic.CbSimple onAction 
            
            
    //订阅事件
            .method public hidebysig specialname instance void add_onAction(class [ESBasic]ESBasic.CbSimple) cil managed synchronized
            {
                ldarg.
    0
                dup
                ldfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                ldarg.
    1
                call 
    class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
                castclass [ESBasic]ESBasic.CbSimple
                stfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                
                ret
            }
            
            
    //取消订阅
            .method public hidebysig specialname instance void remove_onAction(class [ESBasic]ESBasic.CbSimple) cil managed synchronized
            {
                ldarg.
    0
                dup
                ldfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                ldarg.
    1
                call 
    class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
                castclass [ESBasic]ESBasic.CbSimple
                stfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                
                ret
            }
            
            
    //发布事件
            .event [ESBasic]ESBasic.CbSimple OnAction  
            {
                .addon instance 
    void ILTest.Computer::add_onAction(class [ESBasic]ESBasic.CbSimple)
                .removeon instance 
    void ILTest.Computer::remove_onAction(class [ESBasic]ESBasic.CbSimple)
            }
            
            
            
    //*******************  Ctor  **********************************************
            .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
               {               
                ldarg.
    0 
                    call instance 
    void [mscorlib]System.Object::.ctor()
                    ret 
            }
            
            
            
    //*******************  Method  ********************************************
            .method public hidebysig instance void Increase() cil managed        
            {                        
                
    //触发事件
                ldarg.0
                ldfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                ldnull
                ceq
                brtrue.s L_001
                ldarg.
    0
                ldfld 
    class [ESBasic]ESBasic.CbSimple ILTest.Computer::onAction
                callvirt instance 
    void [ESBasic]ESBasic.CbSimple::Invoke()
                nop
                
         L_001: ret            
            }
        }
    }   
                      

    再看ComputerManager实现:

    .namespace ILTest
    {
        .
    class public auto ansi beforefieldinit ComputerManager extends [mscorlib]System.Object
        {
            .field 
    private class [ILTest]ILTest.Computer computer
            .field 
    private int32 handleCount
            
            .method 
    public hidebysig specialname rtspecialname instance void .ctor(class [ILTest]ILTest.Computer) cil managed
               {   
                   ldarg.
    0
                   ldarg.
    1
                   stfld 
    class [ILTest]ILTest.Computer ILTest.ComputerManager::computer
                   
                   ldarg.
    0
                   ldc.i4.
    0
                   stfld int32 ILTest.ComputerManager::handleCount
                   
                   
    //调用基类ctor
                ldarg.0 
                    call instance 
    void [mscorlib]System.Object::.ctor()                
                    
                    
    //预定事件
                   ldarg.0
                   ldfld 
    class [ILTest]ILTest.Computer [ILTest]ILTest.ComputerManager::computer
                   ldarg.
    0
                   ldftn instance 
    void ILTest.ComputerManager::HandleAction()                
                   newobj instance 
    void [ESBasic]ESBasic.CbSimple::.ctor(object ,native int)//生成委托实例需要两个参数:目标对象和要调用的方法的指针
                   callvirt instance void ILTest.Computer::add_onAction(class [ESBasic]ESBasic.CbSimple)    
                   
                   ret
            }
            
            .method 
    public hidebysig instance void HandleAction() cil managed
            {
                ldarg.
    0
                dup
                ldfld int32 ILTest.ComputerManager::handleCount
                ldc.i4.
    1
                add
                stfld int32 ILTest.ComputerManager::handleCount            
                
                ret
            }      
            
            .method 
    public hidebysig instance int32 GetHandleCount() cil managed
            {
                ldarg.
    0
                ldfld int32 ILTest.ComputerManager::handleCount
                
                ret
            }        
        }
    }

    最后,我们写个Main方法来测试一下:

    .namespace ILTest
    {
        .
    class private auto ansi beforefieldinit MainClass
        {
            .method 
    public hidebysig static void Main(string[] args) cil managed
            {
                .entrypoint
                .locals init 
                  (                  
                      [
    0class [ILTest]ILTest.Computer computer,
                      [
    1class [ILTest]ILTest.ComputerManager computerManager,
                      [
    2] int32 count
                  )             
                
                newobj instance 
    void [ILTest]ILTest.Computer::.ctor()    
                stloc.
    0
                ldloc.
    0            
                newobj instance 
    void [ILTest]ILTest.ComputerManager::.ctor(class [ILTest]ILTest.Computer)    
                stloc.
    1
                
                ldloc.
    0
                   dup
                   dup
                   call instance 
    void [ILTest]ILTest.Computer::Increase()
                   call instance 
    void
     [ILTest]ILTest.Computer::Increase()
                   call instance 
    void
     [ILTest]ILTest.Computer::Increase()
                
                ldloc.
    1
                call instance int32 [ILTest]ILTest.ComputerManager::GetHandleCount()
                stloc.
    2
                ldloca.s 
    2            
                call instance 
    string [mscorlib]System.Int32::ToString()
                call 
    void [mscorlib]System.Console::WriteLine( string )    
                call 
    string [mscorlib]System.Console::ReadLine( )
                pop

                ret    
            }
        }
    }

         main方法中调用了Increase方法三次,表示OnAction事件将被触发三次,所以运行后输出的结果是3。

         如果你想使用IL进行应用程序开发,那么我推荐你使用开发环境SharpDevelop,对IL的支持还是不错的(遗憾的是还不支持对IL的代码提示),截图如下:

         

  • 相关阅读:
    如何选择Html.RenderPartial和Html.RenderAction
    [转]使用 HTML5 WebSocket 构建实时 Web 应用
    基于.NET平台常用的框架整理
    0303
    XMLHTTP
    0120如何合并两个使用 System.Xml 使用 Visual C#.NET 的 XML 文档中的数据
    后台动态创建datatable0115
    笔记1126ASP.NET面试题(转)
    笔记1015
    数组与ARRAYLIST的关系与区别(转)
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/1297249.html
Copyright © 2020-2023  润新知