在线的大多数示例(如果不是全部)都将注册处理程序,但随后会返回一个离散的Observable值(即Observable.Return(RecoveryOptionResult.CancelOperation)
)。对于正确的实现,最好将RecoveryOptions
列表作为按钮(或类似内容)的列表呈现给用户,并将流控制传递给用户。
我正在苦苦挣扎的是如何等待用户单击按钮(或更具体地说,如何等待RecoveryOption
命令之一设置其RecoveryResult
)。
我设法一起破解了一些东西,但是我无法想象这种方式是正确的。我缺乏使用reactui的经验,这使我无法概念化监视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
值。但是,似乎必须有更好的方法来做到这一点。 最佳答案
今天再来看一看,我注意到无法观察RecoveryResult
的原因是因为RecoveryOptions
是ReactiveList<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);
}
我将在下一个问题上留下这个答案,希望@ paul-betts可以确认或否认这是适当的策略。
关于c# - 您如何异步使用UserError处理程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30655784/