2

イベントハンドラ

public void DeliverEvent(object sender, EventArgs e)
{

}

#1:これは機能します

public void StartListening(Button source)
{
    source.Click += DeliverEvent;
}

#2: そして、これも..

public void StartListening(EventHandler eventHandler)
{
    eventHandler += DeliverEvent;
}

しかし、#2では、次のようなことをしようとすると、メソッドを呼び出すことができません:

StartListening(button.Click);

次のエラーが表示されます。

The event 'System.Windows.Forms.Control.Click' can only appear on the left hand side of += or -=

そのエラーを回避する方法はありますか? イベントを格納するオブジェクトではなく、イベントをStartListeningメソッドに渡すことができるようにしたい。

4

4 に答える 4

0

Microsoft Reactive ExtensionsまたはRxフレームワークは、イベントをオブザーバブルに変換する方法を提供します。イベントをパラメーターとして渡すことはできませんが、オブザーバブルは可能です。オブザーバブルがサブスクライブされると、基礎となるイベントのハンドラーがセットアップされます。

(オーバーロードの 1 つの) 署名は次のようになります。

IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(
        Action<TDelegate> addHandler, Action<TDelegate> removeHandler
    ) where TEventArgs: EventArgs

たとえばMouseMove、イベントからオブザーバブルを定義するには、次のコードを使用できます。

        IObservable<EventPattern<MouseEventArgs>> mouseMoves =
            Observable
                .FromEventPattern<MouseEventHandler, MouseEventArgs>(
                    h => richTextBox1.MouseMove += h,
                    h => richTextBox1.MouseMove -= h);

次に、次のように参照を渡しIObservable<EventPattern<MouseEventArgs>> mouseMoves、サブスクライブできます。

        var subscription = 
            mouseMoves
                .Subscribe(ep =>
                {
                    var x = ep.EventArgs.X;
                    var y = ep.EventArgs.Y;
                    // etc
                });

オブザーバブル/イベントからのデタッチは、これを呼び出すのと同じくらい簡単になります:

        subscription.Dispose();

Nuget 経由で Rx を取得できます。

于 2012-11-18T23:03:21.477 に答える
0

残念ながら、.net のイベントとプロパティは型システムに存在し、Microsoft がそれらを具体的な型として存在させることは可能であり、有用でしたが (各インスタンスには、追加/削除または追加/削除用のデリゲートのペアが含まれます)。 get/set の場合)、Microsoft はそのような具象型を作成しておらず、作成する可能性もないようです。その結果、プロパティやイベントをルーチンに渡すための見栄えの良い方法はありません。Add代わりに、イベントの場合、メソッド用とメソッド用の 1 組のデリゲートを渡す必要があります。Removeメソッド、または場合によっては、問題の 2 つのデリゲートを保持するクラスまたは構造体を渡すか、またはイベントの名前とともに使用する必要があるイベントを持つオブジェクトを渡し、呼び出されたルーチンでリフレクションを使用して追加/削除ハンドラーを見つけます。名前付きイベントに関連付けられています。

于 2012-11-19T22:49:43.623 に答える