2015-06-04 22 views
3

大多數(如果不是全部)例子在線註冊處理程序,但返回一個離散的可觀察值(即Observable.Return(RecoveryOptionResult.CancelOperation))。爲了正確實現,最好將RecoveryOptions列表作爲按鈕列表(或類似的東西)呈現給用戶,並將流量控制傳遞給用戶。如何異步使用UserError處理程序

什麼我掙扎是如何等待用戶(或者更具體地說,如何等待RecoveryOption命令之一,有其RecoveryResult設置)按鈕點擊。

我設法一起破解的東西確實這個,但我無法想象這種方式是正確的。我缺乏使用reactiveui的經驗,使我無法概念化監控ReactiveList<IRecoveryCommand>的正確方法。

下面是我的黑客代碼。

// UserError.RegisterHandler(x => HandleErrorAsync(x)); 

private async Task<RecoveryOptionResult> HandleErrorAsync(UserError error) 
{ 
    // present error UI... 

    // use ReactiveCommand's IsExecuting observable to monitor changes (since RecoverResult is not an observable) 
    // is there a better way to do this??? this seems sub-optimal 
    await error.RecoveryOptions 
     .Select(x => x.IsExecuting) 
     .Merge() 
     .Where(_ => error.RecoveryOptions.Any(x => x.RecoveryResult.HasValue)) 
     .FirstAsync(); 

    // recovery option was clicked in the UI 

    // get the recovery option that was chosen 
    return error.RecoveryOptions 
     .Where(x => x.RecoveryResult.HasValue) 
     .Select(x => x.RecoveryResult.Value) 
     .First(); 
} 

的主要問題是,RecoveryResult觀察到。所以我必須監測IsExecuting觀察,然後檢查RecoveryResult值。然而,似乎必須有更好的方法來做到這一點。

回答

1

望着這再次今天,我發現我無法觀察RecoveryResult的原因是因爲RecoveryOptionsReactiveList<IRecoveryCommand>IRecoveryCommand是無法觀測。解決此問題的簡單方法是假設所有恢復選項實際上都是RecoveryCommand對象(可觀察到),但更合適的答案是根據IRecoveryCommand合同生成可觀察的流。

我們能夠適應在RxUI docs on Recovery Options描述的代碼做支持RxUI 6.5以下:

public static IObservable<RecoveryOptionResult> GetResultAsync(this UserError This, RecoveryOptionResult defaultResult = RecoveryOptionResult.CancelOperation) 
{ 
    return This.RecoveryOptions.Any() ? 
     This.RecoveryOptions 
      .Select(x => x.IsExecuting 
       .Skip(1) // we can skip the first event because it's just the initial state 
       .Where(_ => x.RecoveryResult.HasValue) // only stream results that have a value 
       .Select(_ => x.RecoveryResult.Value)) // project out the result value 
      .Merge() // merge the list of command events into a single event stream 
      .FirstAsync() : //only consume the first event 
     Observable.Return(defaultResult); 
} 

如果你想支持任何類型的IRecoveryCommand,因爲它立足於它的可觀察數據流,則需要此擴展方法它知道的只有兩個觀察對象之一。不過,如果你可以肯定,你永遠只能處理RecoveryCommand對象,您可以執行以下操作來代替:

public static IObservable<RecoveryOptionResult> GetResultAsync(this UserError This, RecoveryOptionResult defaultResult = RecoveryOptionResult.CancelOperation) 
{ 
    return This.RecoveryOptions.Any() ? 
     This.RecoveryOptions 
      .Cast<RecoveryCommand>() 
      .Select(x => x // our command is now observable 
       // we don't Skip(1) here because we're not observing a property any more 
       .Where(_ => x.RecoveryResult.HasValue) 
       .Select(_ => x.RecoveryResult.Value)) 
      .Merge() 
      .FirstAsync() : 
     Observable.Return(defaultResult); 
} 

我會離開這個答案了下一個,而在希望@保羅 - 貝茨能確認或否認這是適當的策略。