Список (Событий) в VB.NET
Следующее является частью более крупного проекта, но для целей этого вопроса у меня есть следующий код:
Public MustInherit Class Class1(Of T As {System.Windows.Forms.Control, New})
Inherits System.Windows.Forms.UserControl
Friend Items As New Dictionary(Of Integer, T)
Sub Add(ByRef Item As T, ByVal Index As Integer)
Me.Items.Add(Index, Item)
AddHandler Item.Click, AddressOf Class1Click
End Sub
Public Shadows Event Click(ByVal sender As System.Object, ByVal e As System.EventArgs, ByVal Index As Integer)
Sub Class1Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
RaiseEvent Click(sender, e, DirectCast(sender, T).Index)
End Sub
End Class
Public Class Class1CheckBox
Inherits Class1(Of System.Windows.Forms.CheckBox)
End Class
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
...
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.MyClass1 = New Class1CheckBox()
Me.CheckBox1 = New System.Windows.Forms.CheckBox()
Me.CheckBox2 = New System.Windows.Forms.CheckBox()
Me.CheckBox3 = New System.Windows.Forms.CheckBox()
Me.CheckBox4 = New System.Windows.Forms.CheckBox()
Me.SuspendLayout()
...
Me.CheckBox1.Name = "CheckBox1"
Me.CheckBox2.Name = "CheckBox2"
Me.CheckBox3.Name = "CheckBox3"
Me.CheckBox4.Name = "CheckBox4"
...
End Sub
...
Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
Friend WithEvents CheckBox2 As System.Windows.Forms.CheckBox
Friend WithEvents CheckBox3 As System.Windows.Forms.CheckBox
Friend WithEvents CheckBox4 As System.Windows.Forms.CheckBox
Friend WithEvents MyClass1 As Class1CheckBox
End Class
Public Class Form1
Private Sub MyClass1_Click(ByVal sender As Object, ByVal e As System.EventArgs, ByVal Index As Integer) Handles MyClass1.Click
MessageBox.Show(DirectCast(sender, CheckBox).Name)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Controls.OfType(Of CheckBox).AsParallel.ForAll(Sub(n) Me.MyClass1.Add(n, n.Index))
End Sub
End Class
Приведенный выше код работает прекрасно. Каждый раз, когда щелкает один из четырех флажков, даже щелчок перехватывается MyClass1 и обрабатывается MyClass1. Это то, что я хочу.
Проблема в том, что "Клик" жестко закодирован. Обратите внимание, что Class1 является универсальным. Я хочу, чтобы он мог принимать любой класс, который наследует System.Windows.Forms.Control. Некоторые элементы управления могут иметь событие Check, или hover, или GotFocus. Что мне нужно, это что-то следующее, я просто не уверен, каков правильный синтаксис:
Public Class Class1CheckBox
Inherits Class1(Of System.Windows.Forms.CheckBox)
MyBase.AddEvent("Hover", <signature>...)
End Class
Public MustInherit Class Class1(Of T As {System.Windows.Forms.Control, New})
Inherits System.Windows.Forms.UserControl
Friend Items As New Dictionary(Of Integer, T)
Friend Events As New List(Of Event)
Sub AddEvent(EventName As String, ...)
Events.Add(EventName...)
End Sub
Sub Add(ByRef Item As T, ByVal Index As Integer)
Me.Items.Add(Index, Item)
For Each MyEvent As Event In Events
AddHandler ...
Next MyEvent
End Sub
'Public Shadows Event Click(ByVal sender As System.Object, ByVal e As System.EventArgs, ByVal Index As Integer)
'Sub Class1Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
' RaiseEvent Click(sender, e, DirectCast(sender, T).Index)
'End Sub
End Class
Каков правильный синтаксис для создания некоторой последовательности событий, и как я смогу вызвать эти события?
Спасибо,
2 ответа
Как правильно сказать, нужно использовать рефлексию.
Вот простой пример:
Imports System.Reflection
Public MustInherit Class Class1(Of T As {Control, New})
Private _Items As New Dictionary(Of Integer, T)
Private _Events As New Dictionary(Of String, [Event])
Protected Sub AddEvent(eventName As String, [delegate] As [Delegate])
If (Not Me._Events.ContainsKey(eventName)) Then
Dim info As EventInfo = GetType(T).GetEvent(eventName)
If (info Is Nothing) Then
Throw New ArgumentOutOfRangeException("eventName")
End If
Me._Events.Add(eventName, New [Event]([delegate], info))
End If
End Sub
Public Sub AddItem(item As T, index As Integer)
Me._Items.Add(index, item)
For Each [event] As KeyValuePair(Of String, [Event]) In Me._Events
[event].Value.Info.AddEventHandler(item, [event].Value.Delegate)
Next
End Sub
Friend Class [Event]
Friend Sub New([Delegate] As [Delegate], Info As EventInfo)
Me.[Delegate] = [Delegate]
Me.Info = Info
End Sub
Public ReadOnly [Delegate] As [Delegate]
Public ReadOnly Info As EventInfo
End Class
End Class
Public Class Class1CheckBox
Inherits Class1(Of CheckBox)
Public Sub New()
Me.AddEvent("CheckedChanged", New EventHandler(Sub(sender As Object, e As EventArgs) MsgBox(DirectCast(sender, CheckBox).Name & " is checked: " & DirectCast(sender, CheckBox).Checked.ToString())))
End Sub
End Class
То, что вы хотите, не возможно. События являются членами, так же, как методы и свойства. Вы не можете написать код для доступа к любому члену, если не знаете, что тип, который у вас есть, имеет этого члена.
Как и в случае с методами и свойствами, если вы хотите решить, какое событие использовать во время выполнения, вы должны использовать Reflection.