【问题标题】:vb.net dll reflection eventvb.net dll反射事件
【发布时间】: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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 1970-01-01
    • 2013-04-28
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    相关资源
    最近更新 更多