开发者

Custom/Dynamic Methods and Delegates defined at runtime for hanlding events to tell me what event was triggered

Instead of hard-coding all conceivable events handlers, is there a way to do this dynamically at runtime?

What I'm trying to do is define a dynamic method and a dynamic delegate at run-time to handle any conceivable event possible in VB.Net. I'm able to tell an event was triggered and the source object, but I'm not able to tell what event was triggered.

What I'm using now correctly handles most basic events that I'm aware of. However, there's no way to tell me what specific event was triggered. All my handling sub (Trigger_Event() as a partial example below) knows is sender As Object, e As EventArgs. sender is the object that spawned the event, but it will not tell me what even was triggered. EventArgs could be extended, but it will never contain the name of the event as that is not standard practice.

Below are two example class subs currently capable of handling most System.Windows.Forms events that I'm aware of where the event args type can be converted to the standard EventArgs type. Announce_Events() is used to name an event I want to listen to, and fakes a delegate at run-time and currently routes all events to Triggered_Event()...

Public Sub Announce_Events(event_name As String)

Dim obj_type = _a_specific_object.GetType()
Dim obj_event_info = obj_type.GetEvent(event_name, BindingFlags.Instance OR BindingFlags.Public)

Dim obj_event_delegate As [Delegate] = [Delegate].CreateDelegate(obj_event_info.EventHandlerType, Me, "Triggered_Event")
obj_event_info.AddEventHandler(_a_specific_object, obj_event_delegate)
obj_event_delegate = Nothing

End Sub


Private Sub Triggered_Event(sender As Object, e As EventArgs)

' Handle triggered event here

End Sub

I'm having trouble understanding dynamic methods to handle events. Perhaps there's specific function wording I can use to define my handling method at run-time? How can I word Sub Announce_Events() to tell Triggered_Event() what event name was triggered?

Note: all delegates and methods must be dynamically defined in my case unless a single delegate and method can be defined to handle all conceivable events.

Update: Solved by using either solution given by MarkJ and Hans Passant. Here's both versions...

Anon Sub:

Public Sub Announce_Events(event_name As String)

Dim obj_type = _a_specific_object.GetType()
Dim obj_event_info = obj_type.GetEvent(event_name, BindingFlags.Instance OR BindingFlags.Public)
Dim my_event_handler as EventHandler = Sub (sender As Object, e As Object)
    ' do something with sender, e, and event_name variables here '
    End Sub
obj_event_info.AddEventHandler(_a_specific_object, my_event_handler)

End Sub

Defining the Triggered_Event sub is not necessary. However, still need a way to dynamically cast my_event_handler to obj_event_info.EventHandlerType as otherwise it will only work if obj_event_info.EventHandlerType can narrowly convert to EventHandler.

Worker Object:

Public Sub Announce_Events(event_name As String)

Dim obj_type = _a_specific_object.GetType()
Dim obj_event_info = obj_type.GetEvent(event_name, BindingFlags.Instance OR BindingFlags.Public)
Dim e_worker as new Event_Worker(event_name)
Dim obj_event_delegate = [Delegate].CreateDelegate(obj_event_info.EventHandlerType, e_worker, "Triggered_Event")
obj_event_info.AddEventHandler(_a_specific_object, obj_event_delegate)

End Sub

Event_Worker class has an 'event name' field for ref开发者_如何学运维erence on event fire, and contains the "Triggered_Event" sub for processing the fired event while passing along 'event name'. However, "Triggered_Event" must be declared to accept 'e' as strict type 'EventArgs' or at least a narrowing conversion.


Francesco Balena's book Programming Microsoft Visual Basic 2005 The Language has a technique that works in Visual Studio 2005 and 2008. There's a universal event handler routine, which is passed a string identifying the event being fired.

It's a reasonably sized bit of code, and I don't feel I can post such a long excerpt here without the author's permission. Here's a description, which is probably enough to get you going. The code registers the event handlers through reflection, like your code. It creates an instance of a small worker object for each event, to store the name of the event. The worker handles the event and calls its client with an additional argument giving the name of the event. That might sound like a lot of objects and therefore overhead, but I believe it's exactly the same as what the compiler does for you if you use lambda expressions, and substantially less than dynamic methods.

If you buy the book, there's a fuller explanation and the full code.


The problem here of course is that you've only got one event handler for all events. Yes, you'll need to create one handler for one event so you can have an event specific bit of data, like the name. By far the cleanest way to do so is by using a lambda expression. But you'll need the Sub variety, that requires VB.NET version 10 (VS2010).

For prior versions, a dynamic method could indeed solve your problem. Albeit quite painful to get going. Write the code in VB.NET first, use Ildasm.exe to find out what IL you need to generate.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜