Execute a set of commands in order, sequentially with ReactiveUI

谁说胖子不能爱 提交于 2019-12-24 01:45:19

问题


I have a ViewModel with some ReactiveCommands that user can invoke manually.

CommandA
CommandB
CommandC

So the user can invoke only B, or A first, and then C.

The problem is that there is that I want to create another command that runs them in order, from A to C. They shouldn't run in parallel, but sequentially.

How can I do a command of the given characteristics?


回答1:


Import System.Reactive.Linq, now you can:

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

System.Reactive.Linq makes IObservable as awaitable.




回答2:


Since you want them executed sequentially, ReactiveCommand.CreateCombined isn't really a good fit. However, you could create something similar to CombinedReactiveCommand to work for your situation.

Reactive commands can be executed manually by calling ReactiveCommand<TParam,TResult>.Execute, which returns an IObservable<TResult> that returns a single value. Therefore, a very basic implementation could just chain it to other execute calls with SelectMany:

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

If all of your commands have the same type, it could be made more generic:

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

However, this does not take into consideration the other things CombinedReactiveCommand handles, such as CanExecute and ThrownExceptions. If you need to handle those, then you might consider rolling your own CombinedReactiveCommand.




回答3:


I am asuming, that your commands are of type ReactiveCommand<Unit,Unit> so, you can do this:

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

}
}

The utility method InvokeCommand will call another command when a command returns, so this method plus a where clause will do the trick.

I hope this help you Regards



来源:https://stackoverflow.com/questions/51046152/execute-a-set-of-commands-in-order-sequentially-with-reactiveui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!