2011-04-08 40 views
2

處理相關事件的最佳方法是什麼?
有一個對象,我需要測試連接是成功還是失敗。 但是,對象首先需要通過初始化步驟,我測試成功或失敗,然後繼續連接步驟。如何觀察無功擴展(Rx)中的相關事件?

  • 如果初始化失敗,則返回連接失敗。
  • 如果初始化成功,則返回是連接步驟的結果。

我的代碼如下。有沒有更好的方法來處理這些依賴事件,因爲我正在初始化訂閱內部訂閱連接?

如果我有更多這樣的依賴事件,我會繼續嵌套訂閱嗎?

public static void Test() 
{ 
    const int maxValue = 501; 

    var random = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0)); 

    var initOk = Observable.Interval(TimeSpan.FromMilliseconds(random.Next(maxValue))).Select(i => true); 
    var initKo = Observable.Interval(TimeSpan.FromMilliseconds(random.Next(maxValue))).Select(i => false); 

    var connectOk = Observable.Interval(TimeSpan.FromMilliseconds(random.Next(maxValue))).Select(i => true); 
    var connectKo = Observable.Interval(TimeSpan.FromMilliseconds(random.Next(maxValue))).Select(i => false); 

    var initResult = initOk.Amb(initKo).Take(1); 
    var connectResult = connectOk.Amb(connectKo).Take(1); 

    var id = 
     initResult.Subscribe(ir => 
           { 
            if (ir) 
            { 
             var cd = 
              connectResult.Subscribe(cr => 
                     { 
                      Console.WriteLine(cr 
                            ? "Connection succeeded." 
                            : "Connection failed."); 
                     }); 
            } 
            else 
            { 
             Console.WriteLine("Initialization failed thus connection failed."); 
            } 
           }); 
} 

回答

2

通常情況下,您可以通過利用各種rx運算符來鏈接調用來避免嵌套。

你的例子可以使用進行一些清理工作:

initResult.SelectMany(ir => 
     { 
      if (ir != null) 
      { 
      return connectResult; 
      } 

      Console.WriteLine("Initialization failed thus connection failed."); 

      return Observable.Throw(new Exception("Some Exception")); 
     }) 
     .Subscribe(cr => 
      { 
       Console.WriteLine(cr != null 
       ? "Connection succeeded." 
       : "Connection failed."); 
      }) 
+0

謝謝。我明白了。 – 2011-04-08 10:25:41

0

您可以使用此:

var finalResult = 
    initResult 
     .Select(ir => 
      Observable.If(() => ir, connectResult, Observable.Return(false))) 
     .Merge(); 

要得到你的消息了,你可以改變這樣的:

var initResultText = 
    initResult 
     .Select(ir => 
      ir ? (string)null : "Initialization failed thus connection failed."); 

var connectResultText = 
    connectResult 
     .Select(cr => 
      String.Format("Connection {0}.", cr ? "succeeded" : "failed")); 

var finalResult = 
    initResultText 
     .Select(irt => 
      Observable.If(() => 
       irt == null, connectResultText, Observable.Return(irt))) 
     .Merge(); 

如果你需要進一步嵌套,你應該考慮做一個擴展方法來包裝複雜性和星期四組成會更容易。

+0

謝謝。我更喜歡在我的場景中更靈活的SelectMany方法。但你的方法也很可愛。 – 2011-04-09 10:35:23