2016-10-24 14 views
0

私は、DLLから私のメインプログラムにユーザー定義のイベント引数クラスを渡そうとしています。どちらもイベント引数クラスが定義されていますが、イベントデリゲートをメソッドにバインドしようとすると、署名が互換性がないためバインドされません。私は主な問題にコードを削除しました。メインプログラムは、DLLをロードし、メソッドShowValueにイベントデリゲートをバインドvb.net dll反射イベント

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 

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 

DLL内のコードでは、引数としてValueEventArgsととvalueChangeというイベントを発生させますデリゲートと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送信者オブジェクト、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