【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 
              (                  
                  [
0 class  [ILTest]ILTest.Computer computer,
                  [
1 class  [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的代码提示),截图如下:

     

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值