2009-08-06 21 views
13

のコードは以下のようになります。イベントに複数のサブスクライバがある場合、各サブスクライバの戻り値を取得するにはどうすればよいですか?

時計:

public class Clock 
{ 
    public event Func<DateTime, bool> SecondChange; 

    public void Run() 
    { 
     for (var i = 0; i < 20; i++) 
     { 
      Thread.Sleep(1000); 

      if (SecondChange != null) 
      { 
       //how do I get return value for each subscriber? 
       Console.WriteLine(SecondChange(DateTime.Now)); 
      } 
     } 
    } 
} 

DisplayClock:

public class DisplayClock 
{ 
    public static bool TimeHasChanged(DateTime now) 
    { 
     Console.WriteLine(now.ToShortTimeString() + " Display"); 
     return true; 
    } 
} 

LogClock:

public class LogClock 
{ 
    public static bool WriteLogEntry(DateTime now) 
    { 
     Console.WriteLine(now.ToShortTimeString() + " Log"); 
     return false; 
    } 
} 

は、コードを実行するには

他の質問は以下のとおりです。

  • は、それが値を返すために、各加入者のための良い練習ですか?
  • 代理人を手動で宣言するのではなく、単にイベントの戻り値の型としてAction/Funcを宣言するのがよいでしょうか?

答えて

26

Delegate.GetInvocationListを使用してください。

​​

それだけではなく、手動でデリゲートを宣言するのアクション/ FUNCを使用することをお勧めしますか?

はい。しかし、私は、ベストプラクティスはFunc<..., TResult>の代わりにEventHandler<T>を使用するイベントであることを指摘します。 EventHandler<T>は戻り値をサポートしていませんが、返される値を持つ.NETイベントがいくつかあるという点では多少の正当性があります。私はあなたのTとして使用するカスタムEventArgsサブクラスで設定可能なプロパティを持つ方が良いと考えています。これは、KeyEventArgs.Handledのようなものに見られるパターンです。このように、EventHandler<T>を使用することができ、加入者はこのプロパティを取得して設定することによって、限られた範囲で回答を調整することもできます。

+0

ありがとうございました。 – Jeff

+1

そうではありません。 (オブジェクト送信者、EventArgsの)パターンは微妙な良さでいっぱいです。ここで受け入れられた回答の両方を参照してください:http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/83e9f2f4-908b-4679-811d-c5b1471730d7 –

+0

よろしくお願いします。 – Jeff

0

デリゲートの代わりにAction/Funcを使用するのは問題ありません。

BUTイベントは、そのように使用することは想定されていません。 これらは、不確定な時点でトリガーされるため、すべてのパラメータがわからないだけです。あなたが本当に必要なもの

はおそらくです:

  1. はクロック用の多型を使用してください。
  2. visitor/subscriber/observerパターンを使用して値を取得します。

ので、コードは次のようになります。

var theClock = new Clock(); 
theClock.AddSecondsSubscriber(new DisplayClock()); 
theClock.AddSecondsSubscriber(new LogClock()); 
theClock.RunAndExecuteVisitors(theBoolResultYouNeed => Console.WriteLine(theBoolResultYouNeed)); 
関連する問題