简体   繁体   English

vb.net dll反射事件

[英]vb.net dll reflection event

I'm trying to pass a user defined event argument class from a dll to my main program. 我试图将用户定义的事件参数类从dll传递到我的主程序。 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: 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

The Main program loads the dll and binds the event delegate to the method ShowValue: 主程序加载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

If I remove the creation of the delegate and the AddEventHandler everything works without a problem, without the event of course. 如果我删除了委托和AddEventHandler的创建,那么一切都会正常进行,当然不会发生任何事件。

Funny thing, if I change the arguments of ShowValue method in the main program everything suddenly works, including the event. 有趣的是,如果我在主程序中更改ShowValue方法的参数,则所有事件(包括事件)都会突然起作用。

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. 如果在Sub上放置一个断点,我可以看到e包含一个名为Value的属性。
A DirectCast also fails, but writing the EventArgs to a Object seems to work. 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

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? 从dll处理事件时,如何使用用户定义的事件参数类?

I've reached a solution with help of this answer . 借助此答案,我已经找到了解决方案。 I feel like this is the best solution at the moment and it produces usable errors if it fails. 我觉得这是目前最好的解决方案,如果失败,它会产生可用的错误。

The code in the dll and the binding of the method stay unchanged, but the called method now uses reflection to get the Value property. dll中的代码和方法的绑定保持不变,但是被调用的方法现在使用反射来获取Value属性。 Ported to VB.net the method looks like this: 移植到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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM