【发布时间】:2016-10-24 12:44:01
【问题描述】:
我正在尝试将用户定义的事件参数类从 dll 传递到我的主程序。两者都定义了事件参数类,但是当我尝试将事件委托绑定到方法时,它不会绑定,因为它的签名不兼容。我已将代码剥离到主要问题。
dll 中的代码引发一个名为 ValueChange 的事件,其参数为 ValueEventArgs:
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
Main 程序加载 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 的事件时,如何使用用户定义的事件参数类?
【问题讨论】:
-
获取handler方法时需要指定正确的参数类型:
Dim Method As MethodInfo = Me.GetType.GetMethod("ShowValue", New Type() {GetType(Object), DriverAssembly.GetType("ReflectionEventDll.ValueEventArgs")}) -
这似乎不起作用。如果我添加参数并检查调试器,则方法最终为空,表示找不到该方法。当省略参数时,发现该方法没有问题。我还可以在调试器中看到完整的方法名称。
-
你检查过this的答案吗?他最终使用了
Public Sub ShowValue(ByVal sender As Object, ByVal e As EventArgs)并使用反射来获取Value属性。
标签: .net vb.net dll reflection