2009-04-30 13 views
16

このシナリオを検討してください。私はオブジェクトを持っている、それを呼び出すことができます....フー。 Fooは "Loaded"という単純なイベントを発生させます。イベントの情報の一部として、消費者はどのfooオブジェクトがイベントを発生させたのかを知る必要があります。私たちのチームは以下のパターンを採用しました。C#シンプルなイベントの発生 - 「送信者」とカスタムEventArgsの比較

1)EventArgsを継承する新しいクラスを作成します。たとえば、 FooEventArgs:System.EventArgsのようにします。

2)FooEventArgsにFoo型のプロパティを追加します。このプロパティは、コンストラクタを介して渡されることによって設定されます。

3)イベントハンドラのジェネリックバージョンを使用してイベントを宣言し、そう

public event EventHandler<FooEventArgs> Loaded; 
)以下のシグネチャとのFooクラスのイベントを上げ:

Loaded(this, new FooEventArgs(this)); 

は、本質的にこれはないことです"送信者"をfooオブジェクトにしますが、でもは、fooオブジェクト参照をイベント引数に強く型付けされたプロパティとして配置します。

これを行うメリットの1つは、イベントを処理するときに誰も "送信者"をキャストしなくてはならず、イベントコンシューマーとイベントライザー間の結合を低下させることです。別の「利点」は、イベントライザーのタイプが変更されなければならないため、厳密に型指定されたプロパティ(うまくいけないことはない)がnullの場合、単にキャストで失敗するようにするのではなく、 APIが実際にブレークしてコンパイル時に修正される可能性があります。

私にとっては、このパターンは過度なことがあるようです。彼らは "送信者"のパラメータをより信頼し、カスタムイベントの引数を削除する必要がありますか?私のチームは誰も実際に送信側パラメータを使用しないと主張しています。イベントを呼び出すオブジェクトへの参照を渡すためのベストプラクティスは何ですか?

EDIT:今までの偉大なフィードバックは、私が1つを受け入れる前にこれをもう1日ほど開いたままにしておきます。

+4

として頻繁に使用されるDOTNET 1.1を、考えるのは簡単です、あなたは、「イベントの署名を見てしたい場合があります.NETで - 強い型付きの '送信者'を使用していますか? "ここでは:http://stackoverflow.com/questions/1046016/event-signature-in-net-using-a-strong-typed-sender –

答えて

9

一般的なパターンは、送信者を使用し、送信者をEventArgsに別個に追加しないことです。カスタムEventArgsは、ツリーイベントのツリーノード、キャンセル可能なイベントのブール値などの他の状態に使用されます。

BCLクラスでも使用されるため、共通パターンを使用します。 「自作イベント」の違いは潜在的に混乱します。また、グローバルIoCパブリッシャ/サブスクライバパターンもありますが、タイプは事前に分かっていないため、通常のEventHandlerデリゲートシグネチャでのみ動作します。この場合、キャスト(カスタムEventArgsなど)はとにかに必要なので、送信者をキャストするだけでもよいでしょう。

2

私は、大会には多くのことが起こっていると言います。より長期間に渡って維持することは少ない - 特に。

2

私はconsumers will need to know which foo object raised the event.を読んだときには、ある程度の優先度の問題があると思いますが、すぐに送信者の議論からイベントを発生させたオブジェクトを得ることができると思いました問題?

あなたのチームは(強く型付けされたプロパティを持つ)いくつかの有効なポイントを持っていますが、私は独自に発明するのではなく、フレームワークのガイドラインを使って作業することが長期的にはより良い決定になると言います。

3

私はこれが過度だとは思わない。別のFooEventArgsクラスを持っていることの利点に同意します。そうするもう一つの利点は、将来イベントの情報を追加する必要がある場合、FooEventArgsにプロパティを追加するだけで、デリゲートを変更する必要がないことです。

+0

"私はこれもこのようにするのが推奨されるマイクロソフトの慣行だと信じています" - doあなたはこれを参考にしていますか? – Lucero

+0

EventArgsのサブクラスを使用して、イベントに情報を追加することをお勧めします。参照:http://msdn.microsoft.com/en-us/library/aa645739(VS.71).aspxまたはhttp://www.codeproject.com/KB/cs/event_fundamentals.aspx。送信者をeventargsに追加するのは...だから私は尋ねています:p – womp

+0

FooEventArgsがEventArgsから継承する限り、(オブジェクト、EventArgs)という署名付きのデリゲートがイベントを処理できます。したがって、今すぐEventArgsを使用し、後でそれをFooEventArgsに変更することができます。 –

3

EventArgsのサブクラスを削除し、送信者プロパティを使用してイベントの送信者を特定するとします。次の大会の議論にはメリットがあると思いますが、EventArgsのパラメータは必要ありません。私は個人的にそれを落とし、単に送信者のプロパティを使用します。あなたが強いタイプとしてそれを渡したい場合は、あなたも自分のイベントに使用するカスタムデリゲートを作成することができ

...

public delegate void LoadedHandler(FooEventArgs args); 

あなたが強いタイプとしてそれを持っている可能性があり、そのよう..代理人を再利用することは素晴らしいことですが、あなたがしようとしているものに合わない場合は、組み込みのものだけを使用するように制限してはいけません。

2

推奨されている方法では、Windows Workflow Foundationの送信者としてnullがかなり多く提供されています。理想的には、加入者はイベントを発生させるオブジェクトを知らないようにすべきです。

したがって、呼び出し側オブジェクト全体をハンドラに渡す必要がある場合は、EventArgs派生オブジェクトに配置する必要があります。代わりに、私は明示的にイベントライザー/呼び出し元の状態のビットとピースを全部ではなく渡すことを好みます。

まあ、時にはそれが

Control.Invoke() 

はこれに別のアプローチについて

int i; 
+2

あなたは「理想的には、あなたの加入者はイベントを起こすオブジェクトを知らないようにすべきです」と言いますか?それは私が考えることができる出来事のあらゆるユースケースに反しているようです。 –

+0

壮大なデザインでは、evensはアプリケーションドメインの境界、クライアント/サーバーの境界を越えることができるはずです。そして、星間通信でうまくいくはずです:) これは、送信者がこのイベントに関連するすべてのステートフルなものをシリアル化可能な方法でEventArgsの子を介してそれらを提供します。私は、オブジェクトの送信者の議論が絶対的な必要条件となるケースは知らない。 – GregC

関連する問題