2016-05-14 1 views
1

同じイベントを持つ2つのクラスがある場合、それらを1つの名前で参照できるようにしたいと考えています。次のような:実行時に同じイベントで異なるクラスにどのようにアタッチするのですか?

Sub somefunction(select as integer) 
    Dim voidclass 
    if select = 1 then 
     voidclass = myclass1 
    else 
     voidclass = myclass2 
    end if 
    AddHandler voidclass.event1, AddressOf eventhappened 
End Sub 

Sub eventhappened() 
    msgbox("Event occured") 
End Sub 

は明らかに、この例のためのより良い方法があるかもしれませんが、してみましょう:

ここ
Public Class myclass1 
    Public event1() 
End Class 

Public Class myclass2 
    Public event1() 
End Class 

私はどのクラスを使用するために、実行時に決定できるようにしたいと思いますクラスbook1がすでに存在し、book2を作成してsomefunctionを変更することを務めていることを、book1自身で変更することはできません。

上記の例では、エラーevent1は「オブジェクト」のイベントではありません。

プロパティとメソッドはこれで問題ないようですが、イベントはありません。このような状況でイベントを処理するにはどうすればよいですか?

+0

'GetType()'比較と組み合わせたキャストはどうですか?または、他のクラスが派生する基底クラスを作成します。基底クラスにはイベントが含まれます。次に、基本クラスにキャストできます。 –

答えて

1

イベントのインターフェイスを定義し、それをクラスに実装し、インターフェイスの参照を通じてこのイベントを購読することができます。下記を参照してください。

Public Interface INotifier 
    Event SomethingHappened() 
End Interface 

Public Class Class1 
    Implements INotifier 

    Public Event SomethingHappened() Implements INotifier.SomethingHappened 
End Class 

Public Class Class2 
    Implements INotifier 

    Public Event SomethingHappened() Implements INotifier.SomethingHappened 
End Class 

Module Module1 

    Dim notifiers As List(Of INotifier) = New List(Of INotifier) From 
    { 
     New Class1(), 
     New Class2() 
    } 

    Sub Main() 
     SubscribeToEventHandler(0) 
    End Sub 

    Private Sub SubscribeToEventHandler(ByVal index As Integer) 
     Dim notifier As INotifier = notifiers(index) 
     AddHandler notifier.SomethingHappened, AddressOf EventHandler 
    End Sub 

    Private Sub EventHandler() 

    End Sub 

End Module 
2

スニペットは問題とよく一致しません。それは奇妙なバグを持っている、クラスのイベントはShared宣言されていないので、コードは適切なオブジェクト参照を使用する必要があります。タイプ名ではありません。たぶん、答えは同じくらい簡単です:

Private obj1 As myclass1 
    Private obj2 As myclass2 

    Sub somefunction(select as integer) 
     If select = 1 Then 
      AddHandler obj1.event1, AddressOf eventhappened 
     Else 
      AddHandler obj2.event1, AddressOf eventhappened 
     End If 
    End Sub 

しかし、おそらく本当の問題は、同じシナリオですが、今の変数として宣言:

Private obj1, obj2 

型指定されていないので、Object。はい、VB.NETはそれをサポートしていません。 VB.NETのほとんどの欠点と同様に、この背後には歴史があります。 VBはイベントの明示的なレイトバインディングをサポートしていませんでした。メソッドとプロパティのみ。レガシーバージョンのスキームは非常に奇妙でした。 WithEventsキーワードで変数を宣言し、イベントハンドラの特定の名前を選択する必要がありました。言い換えれば:

Dim WithEvents obj1 

    Sub obj1_somethinghappened 
     '' handles the event1 event for obj1 
    End Sub 

また、すべてのイベントが遅延バインドされています。このスキームはVB.NETに引き継がれていませんでした。 WithEventsはまだ存続しますが、メソッド宣言にはHandlesというキーワードが必要です。それはあなたがしたいことをしません。

VB.NETデザイナーは、意図的に遅延バインディングサポートをAddHandlerステートメントに追加しませんでした。私は彼らがこれを決めた正確な理由に関与しておらず、推測しかできない。追加できない技術的な理由はありません。リフレクションコードを生成するためにコンパイラが必要です。一つの可能​​な説明は、彼らはあまりにも高価だと考えているということです。もう1つは、メソッドのシグネチャの不一致が解釈するのが難しい場合に発生するランタイム例外とみなされるということです。私は最後の一番好きです、彼らはひどく醜いです。

あなたはあなたが望むものを得るためにリフレクションを使用する必要があります。 obj1.GetType()。GetEvent( "event1")を使用してEventInfoを取得し、Get/AddMethod()を使用してイベントハンドラを追加します。

Fwiwでは、C#言語の動的キーワードの実装でこれがサポートされています。たぶんあなたはasking for the featureによって耳にバグを置くことができます。これが以前に要求されたのかどうか、本当の考えはありません

関連する問題