2013-04-29 50 views
1

我在问具体的VB.NET,但我想象一般原则在其他语言中是一样的。我认为一个事件是.NET中的一流概念,但从reflection看来,它只是一个特定的方法,它在事件引发时被调用。如何实施事件

  1. 如何AddHandlerRemoveHandler修改方法动态(据我所知,事件pre-日期DynamicMethod S'
  2. 如何RaiseEvent调用的方法?
  3. 为什么AddHandlerRemoveHandler,并RaiseEvent实现陈述而不是方法

回答

2

不,一个事件只是两个或三个方法的组合(“raise”部分是可选的),方法与属性是一个或两个方法的组合相同。

AddHandlerRemoveHandler根本不修改方法。他们只是调用事件的“添加”和“删除”部分,这些部分是实现部分的一部分。

通常情况下,事件通过对具有适当委托类型的字段的引用来实现,其中Delegate.CombineDelegate.Remove用于执行适当的操作。 (字段值将被更改 - 请记住,委托类型是不可变的。)引发事件仅包含调用委托。

至于为什么AddHandler等是单独的语句类型 - 如果它们是方法,参数是什么?有些事情必须提及“事件”。基本上,AddHandler语句对应于适当的事件“add”方法,就像属性获取对应于适当的属性“get”方法一样。你可以用反射做到这一点,通过EventInfo.AddHandler

请参阅我的article on delegates and events了解更多详情,这可能有所帮助 - 它来自C#背景,但其原理显然是相同的。

+0

这是否意味着'RaiseEvent SomeEvent'和'SomeEvent()'具有相同的影响(其中'SomeEvent'被声明为'Public Event SomeEvent As Action')。在VS2010中使用'SomeEvent()'语法给我一个编译错误,我必须使用'RaiseEvent'语法。 – 2013-04-29 14:52:22

+0

@ just.another.programmer:嗯,我相信如果你能够得到这个值,他们会有同样的效果,但是这是VB方面的一个细节,我不太熟悉。 – 2013-04-29 14:54:54

1

事件只是一个代表。下面是一些代码,工程就像一个普通的事件,使用委托对象,而不是玩:

Module Module1 
    Sub Main() 
     Dim obj As New Example 
     obj.AnEvent = New EventHandler(AddressOf Handler) 
     obj.Test() 
     Console.ReadLine() 
    End Sub 

    Sub Handler(ByVal sender As Object, ByVal e As EventArgs) 
     Console.WriteLine("got event") 
    End Sub 
End Module 

Class Example 
    Public AnEvent As EventHandler 
    Public Sub Test() 
     If AnEvent IsNot Nothing Then AnEvent(Me, EventArgs.Empty) 
    End Sub 
End Class 

但是千万注意,此代码的问题。其他一些代码也可能会混淆AnEvent。就像替换它或将其设置回无。在大多数情况下,这是灾难性的,首先订阅事件的代码将停止正常工作。

事件 VB.NET中的关键字可以防止发生这种情况。它包装了委托对象,并使其他代码无法访问,而不是提供的关键字。与财产如何保护对领域的访问有些类似。 AddHandler和RemoveHandler确保现有注册不会消失。 RaiseEvent触发事件,不需要检查Nothing