I'm trying to pass a user defined event argument class from a dll to my main program. Both have the event argument class defined, but when I try to bind the event delegate to the method it won't bind because its signature is not compatible. I've stripped the code down to the main problem.
The code in the dll raises an event called ValueChange with a ValueEventArgs as argument:
Public Class Main
Public Event ValueChange(ByVal sender As System.Object, ByVal e As ValueEventArgs)
Private _Value As Integer
Public Sub Up()
_Value += 1
RaiseEvent ValueChange(Me, New ValueEventArgs(_Value))
End Sub
End Class
Public Class ValueEventArgs
Inherits System.EventArgs
Public Property Value As Integer
Public Sub New(ByVal Value As Integer)
Me.Value = Value
End Sub
End Class
The Main program loads the dll and binds the event delegate to the method ShowValue:
Imports System.Reflection
Public Class Main
Private DriverAssembly As [Assembly]
Private DriverClass As Type
Private DriverClassInstance As Object
Private Sub ButtonLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonLoad.Click
DriverAssembly = [Assembly].Load("reflection_event, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
DriverClass = DriverAssembly.GetType("ReflectionEventDll.Main")
DriverClassInstance = Activator.CreateInstance(DriverClass)
' get the handler method
Dim Method As MethodInfo = Me.GetType.GetMethod("ShowValue")
' get the event and create a delegate
Dim ValueChangeEvent As EventInfo = DriverClass.GetEvent("ValueChange")
Dim Handler As [Delegate] = [Delegate].CreateDelegate(ValueChangeEvent.EventHandlerType, Me, Method) ' Fails
' Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
' add the event handler
ValueChangeEvent.AddEventHandler(DriverClassInstance, Handler)
End Sub
Private Sub ButtonUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonUp.Click
DriverClass.GetMethod("Up").Invoke(DriverClassInstance, Nothing) ' invoke the method on the driver class instance
End Sub
Public Sub ShowValue(ByVal sender As Object, ByVal e As ValueEventArgs)
MessageBox.Show(e.Value.ToString())
End Sub
End Class
Public Class ValueEventArgs
Inherits System.EventArgs
Public Property Value As Integer
Public Sub New(ByVal Value As Integer)
Me.Value = Value
End Sub
End Class
If I remove the creation of the delegate and the AddEventHandler everything works without a problem, without the event of course.
Funny thing, if I change the arguments of ShowValue method in the main program everything suddenly works, including the event.
Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs)
' works, but the Value is lost
End Sub
It gets better, because it's not completely lost. If I put a breakpoint on the Sub I can see e is containing a property called Value.
A DirectCast also fails, but writing the EventArgs to a Object seems to work.
Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs)
Dim Obj As Object = e
MessageBox.Show(Obj.Value.ToString())
End Sub
It works, but I don't think this is the right way. How can I use a user defined event argument class when handling an event from a dll?
Aucun commentaire:
Enregistrer un commentaire