Выполнять набор команд по порядку, последовательно с ReactiveUI - PullRequest
0 голосов
/ 26 июня 2018

У меня есть ViewModel с некоторыми ReactiveCommands, которые пользователь может вызвать вручную.

CommandA
CommandB
CommandC

Таким образом, пользователь может сначала вызвать только B или A , а затем C .

Проблема в том, что Я хочу создать еще одну команду, которая запускает их в порядке , от A до C. Они не должны выполняться параллельно, но последовательно .

Как мне выполнить команду с заданными характеристиками?

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Поскольку вы хотите, чтобы они выполнялись последовательно, ReactiveCommand.CreateCombined не совсем подходит. Однако вы можете создать что-то похожее на CombinedReactiveCommand для работы в вашей ситуации.

Реактивные команды можно выполнить вручную, вызвав ReactiveCommand<TParam,TResult>.Execute, который возвращает IObservable<TResult>, который возвращает одно значение. Следовательно, очень простая реализация может просто связать ее с другими вызовами выполнения с помощью 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, такие как CanExecute и ThrownExceptions. Если вам нужно справиться с этим, то вы можете рассмотреть возможность создания собственной CombinedReactiveCommand.

0 голосов
/ 28 июня 2018

Импорт System.Reactive.Linq, теперь вы можете:

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

System.Reactive.Linq делает IObservable приемлемым.

0 голосов
/ 26 июня 2018

Я предполагаю, что ваши команды имеют тип 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 будет вызывать другую команду при возврате команды, поэтому этот метод плюс предложение where помогут.

Я надеюсь, это поможет вам Привет

...