2011-04-08 72 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