2016-10-24 40 views
0

我想将用户定义的事件参数类从dll传递给我的主程序。两者都定义了事件参数类,但是当我尝试将事件委托绑定到方法时,它不会绑定,因为它的签名不兼容。我已将代码剥离为主要问题。vb.net dll反射事件

在DLL的代码引发与ValueEventArgs作为参数调用ValueChange的事件:

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 

主程序加载DLL和结合事件委托给方法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 

如果我删除了委托和AddEventHandler的创建,那么所有工作都没有问题,当然也没有事件发生。

有趣的是,如果我在主程序中更改ShowValue方法的参数,一切都会突然生效,包括事件。

Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs) 
    ' works, but the Value is lost 
End Sub 

它变得更好,因为它没有完全丢失。如果我在Sub上放置一个断点,我可以看到e包含一个名为Value的属性。
DirectCast也失败了,但是将EventArgs写入对象似乎工作正常。

Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs) 
    Dim Obj As Object = e 
    MessageBox.Show(Obj.Value.ToString()) 
    End Sub 

它的工作原理,但我不认为这是正确的方法。如何在处理来自dll的事件时使用用户定义的事件参数类?

+0

你得到处理方法时,需要specifcy正确的参数类型:'昏暗的方法作为MethodInfo的= Me.GetType.GetMethod(“ShowValue”,新型( ){GetType(Object),DriverAssembly.GetType(“ReflectionEventDll.ValueEventArgs”)})' –

+0

这似乎不起作用。如果我添加参数并检查调试器,则方法结束为空,表示找不到方法。当参数被省略时,该方法没有问题。我也可以在调试器中看到完整的方法名称。 – kleinisfijn

+0

您是否检查过[this](http://stackoverflow.com/a/4756555/2882256)回答?他最终使用Public Sub ShowValue(ByVal sender As Object,ByVal e As EventArgs)'并使用Reflection获取'Value'属性。 –

回答

0

我已经在this answer的帮助下达成了解决方案。我觉得这是目前最好的解决方案,如果失败会产生可用的错误。

dll中的代码和方法的绑定保持不变,但被调用的方法现在使用反射来获取Value属性。移植到VB.net的方法是这样的:

Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs) 
    Dim ValueProperty As PropertyInfo = e.GetType().GetProperty("Value") 
    Dim Value As Integer = Convert.ToInt32(ValueProperty.GetValue(e, Nothing)) 

    MessageBox.Show(Value.ToString()) 
    End Sub