gpt4 book ai didi

c# - ReactiveUI 异常处理

转载 作者:可可西里 更新时间:2023-11-01 08:04:27 25 4
gpt4 key购买 nike

我查看了许多 ReactiveUI 示例,但我看不到一个很好的简单示例来说明如何处理异常,即应该向用户显示一条消息。 (如果有一个很好的例子,有人可以指点我吗?)。

我的第一个问题是如何使用 ReactiveCommand 和 ToProperty 处理异常。例如,我有以下代码:

public class MainWindowViewModel : ReactiveObject
{
public ReactiveCommand CalculateTheAnswer { get; set; }

public MainWindowViewModel()
{
CalculateTheAnswer = new ReactiveCommand();

CalculateTheAnswer
.SelectMany(_ => AnswerCalculator())
.ToProperty(this, x => x.TheAnswer);

CalculateTheAnswer.ThrownExceptions
.Select(exception => MessageBox.Show(exception.Message));
}

private readonly ObservableAsPropertyHelper<int> _theAnswer;
public int TheAnswer
{
get { return _theAnswer.Value; }
}

private static IObservable<int> AnswerCalculator()
{
var task = Task.Factory.StartNew(() =>
{
throw new ApplicationException("Unable to calculate answer, because I don't know what the question is");
return 42;
});

return task.ToObservable();
}
}

我想我一定是误解了 ThrownExceptions,因为当我运行上面的代码时,这个 observable 没有收到任何项目。我做错了什么?

我的第二个问题是如何以 MVVM 友好的方式执行此操作。 This blog entry提到了一个用户错误功能,但我找不到任何关于如何使用它的文档。我将如何在上面的示例中实现它?

编辑:我已经发布了一个示例解决方案on github基于保罗在下面的回答。

最佳答案

您正在理解 ThrownExceptions,但它在错误的人身上,_theAnswer.ThrownExceptions 将收到异常。但棘手的部分是,现在按钮不再起作用——一旦 Observable 结束 OnError,它就永远完成了。

你最终不得不在这里做一些后空翻,比如:

static IObservable<int?> AnswerCalculator()

CalculateTheAnswer
.SelectMany(_ => AnswerCalculator())
.Catch(Observable.Return(null))
.Where(x => x != null)
.Select(x => x.Value)
.ToProperty(this, x => x.TheAnswer);

在这种情况下,ReactiveAsyncCommand 更容易,因为每次调用都会创建一个新的 IObservable,因此您可以:

// ReactiveAsyncCommand handles exceptions thrown for you
CalculateTheAnswer.RegisterAsyncTask(_ => AnswerCalculator())
.ToProperty(this, x => x.TheAnswer);

CalculateTheAnswer.ThrownExceptions.Subscribe(ex => MessageBox.Show("Aieeeee"));

如何使用用户错误

所以,UserError 就像一个旨在向用户抛出的异常(即它包含友好文本,而不是程序员文本)

要使用 UserError,您必须做两件事 - 首先,更改您的 ThrownExceptions:

CalculateTheAnswer.ThrownExceptions
.SelectMany(ex => UserError.Throw("Something bad happened", ex))
.Subscribe(result => /* Decide what to do here, either nothing or retry */);

在您的 View 代码隐藏中,调用“RegisterHandler”:

UserError.RegisterHandler(err => {
MessageBox.Show(err.ErrorMessage);

// This is what the ViewModel should do in response to the user's decision
return Observable.Return(RecoveryOptionResult.CancelOperation);
});

最酷的部分是,这使得错误对话框可测试 - 在单元测试中:

var fixture = new MainWindowViewModel();
bool errorCalled;

using (UserError.OverrideHandlersForTesting(_ => { errorCalled = true; return RecoveryOptionResult.CancelOperation })) {
CalculateTheAnswer.Execute(null);
}

Assert.True(errorCalled);

关于c# - ReactiveUI 异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13949710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com