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;
                }
            });
        }