public void ApplyProjection(IProjection projection, EventStream eventStream) { UniRx.IObservable <IEvent> stream = null; switch (eventStream) { case EventStream.AllExistingEvents: stream = AllEventObservable; // Terminating since it comes from a list break; case EventStream.NewEvents: stream = NewEventObservable; // Unterminating, needs to be cancelled using the CancelToken when desired break; case EventStream.ActionableEvents: stream = AllEventObservable.Where(e => e is IActionableEvent); break; case EventStream.NewActionableEvents: stream = NewEventObservable.Where(e => e is IActionableEvent); break; case EventStream.NonActionableEvents: stream = AllEventObservable.Where(e => !(e is IActionableEvent)); break; case EventStream.NewNonActionableEvents: stream = NewEventObservable.Where(e => !(e is IActionableEvent)); break; default: throw new NotImplementedException(); } projection.Reset(); projection.CancelToken = stream .Finally(() => { projection.OnFinish(); if (projection.CancelToken != null) { projection.CancelToken.Dispose(); projection.CancelToken = null; } }) .Subscribe(e => { if (!projection.Process(e)) { projection.CancelToken.Dispose(); projection.CancelToken = null; } }); }