/// <summary>
        /// Creates a new instance of <see cref="DataLoaderState"/>.
        /// </summary>
        /// <param name="isEmpty">The flag indicating whether the <see cref="DataLoaderState"/> is empty.</param>
        /// <returns><see cref="DataLoaderState"/></returns>
        public DataLoaderState WithIsEmpty(bool isEmpty)
        {
            var newState = new DataLoaderState(this)
            {
                IsEmpty = isEmpty
            };

            return(newState);
        }
        /// <summary>
        /// Creates a new instance of <see cref="DataLoaderState"/>.
        /// </summary>
        /// <param name="data">The data to populate the <see cref="DataLoaderState"/>.</param>
        /// <returns><see cref="DataLoaderState"/></returns>
        public DataLoaderState WithData(object data)
        {
            var newState = new DataLoaderState(this)
            {
                Data      = data,
                IsInitial = false
            };

            return(newState);
        }
        private int _sequenceId = -1;                                // This field is used to generate the SequenceId of each IDataLoaderRequest.

        public DataLoader(string name, IDataLoaderStrategy strategy, DataLoaderConcurrentMode concurrentMode, Func <IDataLoaderState, bool> emptySelector)
        {
            Name            = name ?? throw new ArgumentNullException(nameof(name));
            _concurrentMode = concurrentMode;
            _emptySelector  = emptySelector ?? throw new ArgumentNullException(nameof(emptySelector));
            _strategy       = strategy ?? throw new ArgumentNullException(nameof(strategy));
            _state          = DataLoaderState.Default;
            _triggers       = new List <IDataLoaderTrigger>();
            _contextValues  = new Dictionary <string, object>();
            _logger         = this.Log();
        }
        private void UpdateState(Func <DataLoaderState, DataLoaderState> update)
        {
            var previousState = _state;

            _state = update(_state);
            _state = _state.WithIsEmpty(_emptySelector(_state));

            if (!Equals(previousState, _state))
            {
                StateChanged?.Invoke(this, _state);
            }
            else
            {
                if (_logger.IsEnabled(LogLevel.Trace))
                {
                    _logger.LogTrace($"Discarded state changed event because the new state is equal to the previous.");
                }
            }
        }