×

VB.NET下的事件和委托

Kalet Kalet 发表于2009-03-20 12:00:14 浏览176 评论0

抢沙发发表评论

委托是可用于调用其他对象方法的对象。它们有时被称为类型安全函数指针,因为它们与其他编程语言 中所使用的函数指针相似。但不同于函数指针,Visual Basic .NET 委托是基于 System.Delegate 类的引用类型,它可以引用共享方法 —无需特定的类实例即可调用的方法和实例方法。



委托在调用过程和被调用过程需要媒介的情况下是很有用的。例如,您可能想让一个引发事件的对象能够在不同的环境下调用不同的事件处理程序。不幸的是,引发事件的对象无法提前知道处理特定事件的事件处理程序。Visual Basic .NET 通过在使用 AddHandler 语句时创建委托,可让您动态地将事件处理程序与事件关联。在运行时,委托将各种调用转发到相应的事件处理程序。

VB.NET下的事件和委托

尽管可以创建自己的委托,但在大多数情况下,Visual Basic .NET 为您创建委托并提供具体信息。例如,Event 语句将名为 <EventName>EventHandler 的委托类隐式定义为 Event 语句所在类的嵌套类,且其签字与该事件相同。AddressOf 语句则隐式创建委托的实例。例如,以下两行代码是等效的:

AddHandler Button1.Click, AddressOf Me.Button1_Click   ' AddHandler 指向引发事件的对象,AddressOf则确定该事件对象所要调用的事件处理程序
'上述行为又可以称为 监 视AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)

只要编译器可以用上下文确定委托的类型,就可以使用速写方法创建委托。
注:处理自基类继承的事件
派生类(继承某个基类特征的类)能用 Handles MyBase 语句处理它们的基类所引发的事件。
处理来自基类的事件
通过给事件处理程序过程的声明行添加 Handles MyBase.<event name> 语句来声明派生类中的事件处理程序,其中的 event name 是基类中正在处理的事件的名称。例如:
Public Class Class1
   Public Event SE(ByVal i As Integer)
   ' Place methods and properties here.
End Class


Public Class Class2
   Inherits Class1
   Sub EventHandler(ByVal x As Integer) Handles MyBase.SE
   ' Place code to handle events from Class1 here.
   End Sub
End Class


声明使用现有委托类型的事件


某些情况下,可能会要声明某事件使用现有委托类型为基础委托。以下语法说明了进行声明的方式:

Event AnEvent As DelegateType

该语法在将多个事件路由到同一处理程序时是很有用的,不过使用现有委托类型时需要先进行如下定义:
delegate {sub|function} DelegateType(参数1,参数2)
下面是vb.net控制台程序演示单一事件委托多处理程序.  
比如说在社会上,你是法律,社会上有三种人,警察、无赖和自愿反扒队。
你规定:如果小偷偷东西,则警察处罚小偷500元钱,自愿反扒队要打无赖进医院一次
    
这就是现实中的委托。

实际上,在写程序中,程序员就是法律,警察、小偷和自愿反扒队就是三个对象。小偷偷东西是一个方法,小偷还有一个偷东西事件,他偷东西激发这个事件。而警察和自愿反扒队就是两个事件处理对象,警察负责把小偷的钱扣除500,自愿反扒队需要大小偷进医院一次。
    
所以,委托有如下几个要素:
1 激发事件的对象--就是小偷   
2 处理对象事件的对象--就是警察和自愿反扒队
3 定义委托,就是法律让警察和自愿反扒队监视小偷。

如果这三个要素都满足的话,则你就写出了一个完整事件的处理。
下面是VB.NET控制台的实例
Imports System
Module Module1
    '准备引用 无赖 类的偷东西事件
    Public WithEvents w As 无赖
    Sub Main()
        Console.WriteLine("新的一天开始了....")
        ' 实例华警察、无赖、自愿反扒队 类
        Dim p As New 警察
        w = New 无赖
        Dim pp As New 自愿反扒队
        '设置对无赖类的偷东西事件的监视,并设置相应的事件处理程序
        '如果小偷玩偷东西则引用警察的罚钱处理程序
        AddHandler w.PlayGame, AddressOf p.扣钱
        '如果小偷偷东西则引用自愿反扒队的打人处理程序
        AddHandler w.PlayGame, AddressOf pp.打人
        w.偷东西()
        Console.WriteLine("天黑了....")
        Console.ReadLine()
    End Sub
    ' End Class



    Public Class 警察
        Sub New()
            Console.WriteLine("生成警察......")
        End Sub
        '定义的事件处理程序的参数类型要与定义的委托的参数类型相一致
        Public Sub 扣钱(ByVal sender As Object, ByVal e As System.EventArgs)


            Console.WriteLine("警察:好小子,胆敢偷东西...")
            '定义线程输出迟缓3秒
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("警察:看看你小子有多少钱...")
            Dim f As 无赖 = sender
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("无赖 的钱:   " + f.钱.ToString())VB.NET下的事件和委托
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("开始扣钱......")
            System.Threading.Thread.Sleep(3000)
            f.钱 = f.钱 - 500
            Console.WriteLine("扣完了....现在无赖 还剩下:" + f.钱.ToString())
            System.Threading.Thread.Sleep(3000)
        End Sub


    End Class
    Public Class 无赖
        '先定义一个偷东西的事件使用现有委托类型 PlayGameHandler为基础委托
        Public Event PlayGame As PlayGameHandler
        Private m_Money As Integer
        Private ey As Integer
        Sub New()
            Console.WriteLine("生成无赖....")
            m_Money = 1000
            ey = 5
        End Sub
        '定义挨打属性用来记录挨打过几次
        Property 挨打() As Integer
            Get
                Return ey
            End Get
            Set(ByVal Value As Integer)
                ey = Value
            End Set
        End Property
        '定义前属性用来记录有多少钱
        Property 钱() As Integer
            Get
                Return m_Money
            End Get
            Set(ByVal Value As Integer)
                m_Money = Value
            End Set
        End Property
        '定义偷东西过程
        Public Sub 偷东西()
            Console.WriteLine("无赖开始偷东西了")
            System.Threading.Thread.Sleep(3000)
            '实例化事件参数
            Dim e As New System.EventArgs
            '引发偷东西事件,参数类型要与现有委托类型一致
            RaiseEvent PlayGame(Me, e)
        End Sub
    End Class
    Public Class 自愿反扒队
        Sub New()
            Console.WriteLine("自愿反扒队来了.....")
            System.Threading.Thread.Sleep(3000)
        End Sub
        '定义的事件处理程序的参数类型要与定义的委托的参数类型相一致
        Public Sub 打人(ByVal sender As Object, ByVal e As System.EventArgs)
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("自愿反扒队:好小子,敢偷东西...")
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("自愿反扒队:你小子挨过几次打了...")
            Dim bn As 无赖 = sender
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("无赖:" + bn.挨打.ToString + "次")
            System.Threading.Thread.Sleep(3000)


            Console.WriteLine("自愿反扒队:那也得揍你,先来一拳....   ")
            System.Threading.Thread.Sleep(3000)
            Console.WriteLine("自愿反扒队:再来一脚......")
            System.Threading.Thread.Sleep(3000)


            Console.WriteLine("自愿反扒队:打完了...赶紧去医院吧...")
        End Sub
    End Class
    '定义委托类型
    Delegate Sub PlayGameHandler(ByVal sender As Object, ByVal e As System.EventArgs)VB.NET下的事件和委托
End Module



群贤毕至

访客