StartWith () после Switch () за исключением начальной подписки - PullRequest
1 голос
/ 01 апреля 2020

У меня есть IObservable<string>, который Switch() исключается каждый раз, когда другое IObservable выдает значение, например так:

IObservable<string> Invalidated => stateChanged
    .Select(state => state.CanExecuteChanged.Select(x => _myString))
    .Switch()
    .StartWith(_myString);

Здесь stateChanged является IObservable<State> и CanExecuteChanged является IObservable<bool>. Другими словами, каждый раз, когда состояние изменяется, я отписываюсь от наблюдаемой state CanExecuteChanged и подписываюсь на наблюдаемую, предоставляемую новым состоянием.

Проблема связана с StartWith. В первый раз, когда я подписываюсь , я не хочу, чтобы значение выдавалось . Однако каждый раз, когда Switch выполняется в результате изменения состояния , я хочу, чтобы значение было передано . Иными словами, при первоначальной подписке на Invalidated значение не должно выдаваться, но при каждом Switch, следовательно, я хочу, чтобы значение выдавалось. Могу ли я достичь этого, и если да, то как?

1 Ответ

0 голосов
/ 30 апреля 2020

Уверен, что @Asti был здесь. Вот некоторые тесты, показывающие, что при перемещении StartWith внутри проекции:

  1. При первоначальной подписке не генерируется значение
  2. "Начальное" значение генерируется, когда наблюдаемое состояние испускает новое значение
  3. "измененное" значение выдается, когда наблюдаемая CanExecuteChanged изменится
public class State
{
    public State(IObservable<bool> canExecuteChanged)
    {
        CanExecuteChanged = canExecuteChanged;
    }

    public IObservable<bool> CanExecuteChanged { get; }
}

public class StartWithAfterSwitch
{
    private IObservable<string> CreateObservable(IObservable<State> state)
    {
        return state
            .Select(s => s.CanExecuteChanged.Select(_ => "changed").StartWith("initial"))
            .Switch();
    }

    [Test]
    public void ShouldNotEmmitOnInitialSubscription()
    {
        var scheduler = new TestScheduler();

        var states = scheduler.CreateColdObservable<State>();

        var observed = scheduler.Start(() => CreateObservable(states), TimeSpan.FromSeconds(1).Ticks);

        Assert.That(observed.Messages, Is.Empty);
    }

    [Test]
    public void ShouldEmitWhenStateChanges()
    {
        var scheduler = new TestScheduler();

        State stateA = new State(Observable.Never<bool>());

        var states = scheduler.CreateColdObservable(
            new Recorded<Notification<State>>(TimeSpan.FromMilliseconds(500).Ticks, Notification.CreateOnNext(stateA)) 
        );

        var observed = scheduler.Start(() => CreateObservable(states), TimeSpan.FromSeconds(1).Ticks);

        Assert.That(observed.Messages.Count, Is.EqualTo(1));
        Assert.That(observed.Messages[0].Time, Is.EqualTo(TimeSpan.FromMilliseconds(500).Ticks).Within(TimeSpan.FromMilliseconds(1).Ticks));
        Assert.That(observed.Messages[0].Value.Value, Is.EqualTo("initial"));
    }

    [Test]
    public void ShouldEmitWhenCanExecuteChanges()
    {
        var scheduler = new TestScheduler();

        State stateA = new State(scheduler.CreateColdObservable(
            new Recorded<Notification<bool>>(TimeSpan.FromMilliseconds(100).Ticks, Notification.CreateOnNext(true))
        ));

        var states = scheduler.CreateColdObservable(
            new Recorded<Notification<State>>(TimeSpan.FromMilliseconds(500).Ticks, Notification.CreateOnNext(stateA))
        );

        var observed = scheduler.Start(() => CreateObservable(states), TimeSpan.FromSeconds(1).Ticks);

        Assert.That(observed.Messages.Count, Is.EqualTo(2));
        Assert.That(observed.Messages[0].Time, Is.EqualTo(TimeSpan.FromMilliseconds(500).Ticks).Within(TimeSpan.FromMilliseconds(1).Ticks));
        Assert.That(observed.Messages[0].Value.Value, Is.EqualTo("initial"));

        Assert.That(observed.Messages[1].Time, Is.EqualTo(TimeSpan.FromMilliseconds(600).Ticks).Within(TimeSpan.FromMilliseconds(1).Ticks));
        Assert.That(observed.Messages[1].Value.Value, Is.EqualTo("changed"));
    }
}
...