protected async Task <RepositoryResult <T> > LoadFromCacheThenRefreshAsync <T>(
            string key,
            DateTime?updatedTime,
            Func <T, DateTime> updatedTimeFunc,
            TimeSpan staleAfter,
            TimeSpan expireAfter,
            Func <Task <ServiceResult <T> > > getDataFuncAsync,
            Func <RepositoryResult <T>, Task> refreshActionAsync = null
            )
        {
            try
            {
                var useUpdatedTime = updatedTime != null;
                var cacheItem      = useUpdatedTime
                    ? await _cacheService.GetAsync <T>(key, updatedTime.Value)
                    : await _cacheService.GetAsync <T>(key);

                if (cacheItem.HasValue &&
                    !cacheItem.IsStale &&
                    !cacheItem.IsExpired)
                {
                    return(RepositoryResult <T> .Create(cacheItem.Value));
                }

                if (cacheItem.HasValue &&
                    cacheItem.IsStale &&
                    !cacheItem.IsExpired &&
                    refreshActionAsync != null)
                {
                    refreshActionAsync(RepositoryResult <T> .Create(cacheItem.Value, false));
                }

                var serviceResult = await getDataFuncAsync().ConfigureAwait(false);

                if (serviceResult.Successful)
                {
                    if (useUpdatedTime)
                    {
                        // ReSharper disable once CSharpWarnings::CS4014, no need to wait storage operation
                        _cacheService.PutAsync(key, updatedTimeFunc(serviceResult.Value), serviceResult.Value,
                                               DateTime.Now + staleAfter, DateTime.Now + expireAfter);
                    }
                    else
                    {
                        // ReSharper disable once CSharpWarnings::CS4014, no need to wait storage operation
                        _cacheService.PutAsync(key, serviceResult.Value,
                                               DateTime.Now + staleAfter, DateTime.Now + expireAfter);
                    }
                }
                return(serviceResult);
            }
            catch (Exception xcp)
            {
                return(RepositoryResult <T> .CreateError(xcp));
            }
        }
        protected async Task <RepositoryResult <T> > AppendToCacheAsync <T>(
            string key,
            DateTime?updatedTime,
            Func <Task <ServiceResult <T> > > getDataFuncAsync,
            Func <T, T, T> updateDataFunc,
            Func <T, T, T> filterDataFunc
            )
        {
            try
            {
                var serviceResult = await getDataFuncAsync().ConfigureAwait(false);

                if (serviceResult.Successful)
                {
                    var useUpdatedTime = updatedTime != null;
                    var cacheItem      = useUpdatedTime
                        ? await _cacheService.GetAsync <T>(key, updatedTime.Value).ConfigureAwait(false)
                        : await _cacheService.GetAsync <T>(key).ConfigureAwait(false);

                    if (cacheItem.HasValue)
                    {
                        var filteredItems = filterDataFunc(cacheItem.Value, serviceResult.Value);
                        if (useUpdatedTime)
                        {
                            // ReSharper disable once CSharpWarnings::CS4014, no need to wait storage operation
                            _cacheService.UpdateAsync(key, updatedTime.Value, updateDataFunc(cacheItem.Value, serviceResult.Value));
                        }
                        else
                        {
                            // ReSharper disable once CSharpWarnings::CS4014, no need to wait storage operation
                            _cacheService.UpdateAsync(key, updateDataFunc(cacheItem.Value, serviceResult.Value));
                        }
                        return(filteredItems);
                    }
                }
                return(serviceResult);
            }
            catch (Exception xcp)
            {
                return(RepositoryResult <T> .CreateError(xcp));
            }
        }