ReactiveUI异常处理(ReactiveUI exception handling)

2019-07-05 21:02发布

我在一个数量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,因为这可观察到的未接收到任何物品,当我运行上面的代码。 我究竟做错了什么?

我的第二个问题是如何将我的MVVM友好的方式做到这一点。 这篇博客提到了用户错误的功能,但我无法找到如何使用它的任何文件。 我将如何落实到上面的例子?

编辑 :我已经发表了示例解决方案在github上基于以下保罗的回答。

Answer 1:

你了解ThrownExceptions ,但它是在错误的家伙, _theAnswer.ThrownExceptions会收到异常。 但棘手的部分,是现在按钮不工作了 - 一次可观察到的两端的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就像是打算在用户被抛出(即它包含友好的文本,不是程序员文本)异常

要使用UserError ,你必须做两两件事-第一,改变你的ThrownExceptions:

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

而在您查看代码隐藏,调用`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);


文章来源: ReactiveUI exception handling
标签: c# reactiveui