使用 ReactiveUI 按顺序执行一组命令

Execute a set of commands in order, sequentially with ReactiveUI

我有一个 ViewModel,其中一些 ReactiveCommands 用户可以手动调用。

CommandA
CommandB
CommandC

所以用户只能调用B,或者先调用A,再调用C .

问题是我想创建另一个命令运行按顺序从A到C排列它们。它们不应该运行 并行,但 顺序 .

如何执行给定特征的命令?

我假设你的命令是 ReactiveCommand<Unit,Unit> 类型,所以你可以这样做:

public class MyCoolViewModel
{
   bool runSequentially = false;

   public ReactiveCommand<Unit, Unit> Command { get; set; }
   public ReactiveCommand<Unit, Unit> Command2 { get; set; }
   public ReactiveCommand<Unit, Unit> Command3 { get; set; }
   public ReactiveCommand<Unit, Unit> CommandwhoInvokesOtherCommands { get; set; }


   public MyCoolViewModel()
   {

       Command = ReactiveCommand.CreateFromTask<Unit, Unit>(async _ =>
       {    
        runSequentially= false;
        Console.WriteLine("Start 1");
        await Task.Delay(1000);
        Console.WriteLine("End 1");
        return Unit.Default;
       });
      Command2 = ReactiveCommand.CreateFromTask<Unit, Unit>(async _ =>
      {
        runSequentially = false;
        Console.WriteLine("Start 2");
        await Task.Delay(1000);
        Console.WriteLine("End 2");
        return Unit.Default;
      });

    Command3 = ReactiveCommand.CreateFromTask<Unit, Unit>(async _ =>
    {
        Console.WriteLine("Start 3");
        await Task.Delay(1000);
        Console.WriteLine("End 3");
        return Unit.Default;
    });

    CommandwhoInvokesOtherCommands = ReactiveCommand.CreateFromTask<Unit, Unit>(async _ =>
      {
          Console.WriteLine("Invoking other commands");
          runSequentially = true;
          await Task.Delay(1000);
          Console.WriteLine("End");
          return Unit.Default;
      });

            /*Command 1, 2 and 3 only will run if flag is set to true*/
    CommandwhoInvokesOtherCommands.Where(_ => runSequentially).InvokeCommand(Command);
    Command.Where(_ => runSequentially).InvokeCommand(Command2);
    Command2.Where(_ => runSequentially).InvokeCommand(Command3);

    //Observable.Return(Unit.Default).InvokeCommand(CommandwhoInvokesOtherCommands);//for test purposes

}
}

实用方法 InvokeCommand 会在一个命令 returns 时调用另一个命令,所以这个方法加上一个 where 子句就可以了。

希望对你有帮助 问候

由于您希望它们按顺序执行,ReactiveCommand.CreateCombined isn't really a good fit. However, you could create something similar to CombinedReactiveCommand 适合您的情况。

响应式命令可以通过调用 ReactiveCommand<TParam,TResult>.Execute 手动执行,其中 returns 和 IObservable<TResult> returns 单个值。因此,一个非常基本的实现可以将它链接到其他执行调用 SelectMany:

ReactiveCommand.CreateFromObservable(() =>
    CommandA.Execute()
        .SelectMany(_ => CommandB.Execute())
        .SelectMany(_ => CommandC.Execute()));

如果您的所有命令都具有相同的类型,它可以变得更通用:

var commands = new[] { CommandA, CommandB, CommandC };
ReactiveCommand.CreateFromObservable(() =>
    commands.Aggregate(
        Observable.Return(Unit.Default),
        (acc, cur) => acc.SelectMany(_ => cur.Execute())));

然而,这并没有考虑 CombinedReactiveCommand 处理的其他事情,例如 CanExecuteThrownExceptions。如果您需要处理这些,那么您可以考虑推出自己的 CombinedReactiveCommand。

导入System.Reactive.Linq,现在您可以:

{
    await CommandA.Execute();
    await CommandB.Execute();
    await CommandC.Execute();
}

System.Reactive.Linq 使 IObservable 成为可等待的。