Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用异步扩展方法时,订阅observable不触发_C#_Wpf_System.reactive_Reactiveui_Rx.net - Fatal编程技术网

C# 使用异步扩展方法时,订阅observable不触发

C# 使用异步扩展方法时,订阅observable不触发,c#,wpf,system.reactive,reactiveui,rx.net,C#,Wpf,System.reactive,Reactiveui,Rx.net,对于一个新项目,我使用的是ReactiveUI。我开始真的喜欢反应式编程背后的想法,但仍有一些问题困扰着我去理解一些概念和编写惯用代码 在本例中,我有一个非常基本的主窗口,其中有一个名为“UserId”的文本框: 我可以想象一个tryparsent扩展方法,但也许它不是必需的 编辑 根据@GlennWatson的答案更新了扩展方法,它现在可以正常工作了: public static IObservable<TResult> Match<TSuccess, TFailure, T

对于一个新项目,我使用的是ReactiveUI。我开始真的喜欢反应式编程背后的想法,但仍有一些问题困扰着我去理解一些概念和编写惯用代码

在本例中,我有一个非常基本的主窗口,其中有一个名为“UserId”的文本框:

我可以想象一个tryparsent扩展方法,但也许它不是必需的

编辑

根据@GlennWatson的答案更新了扩展方法,它现在可以正常工作了:

public static IObservable<TResult> Match<TSuccess, TFailure, TResult>(
    this IObservable<Result<TSuccess, TFailure>> source,
    Func<TSuccess, Task<TResult>> success,
    Func<TFailure, Task<TResult>> failure)
    => source.SelectMany(r => r.Match(success, failure).ToObservable());
公共静态IObservable匹配(
这是一个可观测的来源,
Func成功,
功能失效)
=>source.SelectMany(r=>r.Match(success,failure).ToObservable());
FromAsync()方法仅用于基于任务的系统

当使用可观察的和后续Linq风格的方法时,尽量使其保持可观察的形式


在您的示例中,您正在等待一个可观察对象,并将其包装为FromAsync。SelectMany有一个重载,可以理解基于任务的操作。

源是可观察的,所以我不会使用FromAsync()并将其视为任务。SelectMany应该为您包装任务。
using System.Reactive.Disposables;
using System.Windows;
using ReactiveUI;

namespace ReactiveUiDemo
{
    public partial class MainWindow : Window, IViewFor<MainWindowViewModel>
    {
        public MainWindowViewModel ViewModel { get; set; }

        object IViewFor.ViewModel
        {
            get => ViewModel;
            set => ViewModel = (MainWindowViewModel)value;
        }

        public MainWindow()
        {
            InitializeComponent();
            ViewModel = new MainWindowViewModel();

            this.WhenActivated(disposables =>
            {
                this
                    .Bind(ViewModel, vm => vm.UserId, v => v.UserId.Text)
                    .DisposeWith(disposables);
            });
        }
    }
}
using System;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace ReactiveUiDemo
{
    public sealed class MainWindowViewModel : ReactiveObject
    {
        [Reactive]
        public string UserId { get; private set; }

        public MainWindowViewModel()
        {
            this
                .WhenAnyValue(t => t.UserId)
                .Where(u => (u?.Length ?? 0) == 4)
                .Where(u => int.TryParse(u, out _))
                .Select(i => int.Parse(i))
                .Select(i => GetUserName(i))
                .Match(
                    userName => DisplaySuccess(userName),
                    failure => DisplayError(failure))
                .Do(_ => UserId = string.Empty)
                .Subscribe(
                    _ => MessageBox.Show("OnNext"),
                    _ => MessageBox.Show("OnError"),
                    () => MessageBox.Show("OnCompleted"));
        }

        private enum Failure { UserNotFound }

        private Result<string, Failure> GetUserName(int userId)
        {
            if (userId == 1234)
                return "Waldo";

            return Failure.UserNotFound;
        }

        private async Task<Unit> DisplayError(Failure failure)
        {
            MessageBox.Show($"Error: {failure}.");
            await Task.CompletedTask;

            return Unit.Default;
        }

        private async Task<Unit> DisplaySuccess(string userName)
        {
            MessageBox.Show($"Found {userName}!");
            await Task.CompletedTask;

            return Unit.Default;
        }
    }
}
using System;

namespace ReactiveUiDemo
{
    public sealed class Result<TSuccess, TFailure>
    {
        private readonly bool _isSuccess;
        private readonly TSuccess _success;
        private readonly TFailure _failure;

        private Result(TSuccess value)
        {
            _isSuccess = true;
            _success = value;
            _failure = default;
        }

        private Result(TFailure value)
        {
            _isSuccess = false;
            _success = default;
            _failure = value;
        }

        public TResult Match<TResult>(Func<TSuccess, TResult> successFunc, Func<TFailure, TResult> failureFunc)
            => _isSuccess ? successFunc(_success) : failureFunc(_failure);

        public static implicit operator Result<TSuccess, TFailure>(TSuccess value)
            => new Result<TSuccess, TFailure>(value);

        public static implicit operator Result<TSuccess, TFailure>(TFailure value)
            => new Result<TSuccess, TFailure>(value);
    }
}
using System;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;

namespace ReactiveUiDemo
{
    public static class ObservableExtensions
    {
        public static IObservable<TResult> Match<TSuccess, TFailure, TResult>(
            this IObservable<Result<TSuccess, TFailure>> source,
            Func<TSuccess, Task<TResult>> success,
            Func<TFailure, Task<TResult>> failure)
            => Observable.FromAsync(async () => await source.SelectMany(result => result.Match(success, failure).ToObservable()));
    }
}
                .Where(u => (u?.Length ?? 0) == 4)
                .Where(u => int.TryParse(u, out _))
                .Select(int.Parse)
public static IObservable<TResult> Match<TSuccess, TFailure, TResult>(
    this IObservable<Result<TSuccess, TFailure>> source,
    Func<TSuccess, Task<TResult>> success,
    Func<TFailure, Task<TResult>> failure)
    => source.SelectMany(r => r.Match(success, failure).ToObservable());