/// <summary>
        /// Sets a value with the given key.
        /// </summary>
        /// <param name="key">A long? identifying the requested value.</param>
        /// <param name="value">The value to set in the cache.</param>
        /// <param name="options">The cache options for the value.</param>
        /// <exception cref="ArgumentNullException">key or value or options</exception>
        public void Set(string key, IOStream value, StreamCacheEntryOptions options)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            var entryOptions = new MemoryCacheEntryOptions
            {
                AbsoluteExpiration = options.AbsoluteExpiration,
                AbsoluteExpirationRelativeToNow = options.AbsoluteExpirationRelativeToNow,
                SlidingExpiration = options.SlidingExpiration,
                Size = value is StreamWithHeader z ? z.TotalLength : value.Length,
            };

            _memCache.Set(key, value, entryOptions);
        }
        static DateTimeOffset?GetAbsoluteExpiration(DateTimeOffset creationTime, StreamCacheEntryOptions options)
        {
            if (options.AbsoluteExpiration.HasValue && options.AbsoluteExpiration <= creationTime)
            {
                throw new ArgumentOutOfRangeException(nameof(DistributedCacheEntryOptions.AbsoluteExpiration), options.AbsoluteExpiration.Value, "The absolute expiration value must be in the future.");
            }
            var absoluteExpiration = options.AbsoluteExpiration;

            if (options.AbsoluteExpirationRelativeToNow.HasValue)
            {
                absoluteExpiration = creationTime + options.AbsoluteExpirationRelativeToNow;
            }
            return(absoluteExpiration);
        }
        /// <summary>
        /// Sets the value with the given key.
        /// </summary>
        /// <param name="key">A long identifying the requested value.</param>
        /// <param name="value">The value to set in the cache.</param>
        /// <param name="options">The cache options for the value.</param>
        /// <param name="token">Optional. The <see cref="T:System.Threading.CancellationToken" /> used to propagate notifications that the operation should be canceled.</param>
        /// <returns>
        /// The <see cref="T:System.Threading.Tasks.Task" /> that represents the asynchronous operation.
        /// </returns>
        /// <exception cref="ArgumentNullException">key or value or options</exception>
        public Task SetAsync(string key, IOStream value, StreamCacheEntryOptions options, CancellationToken token = default)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            token.ThrowIfCancellationRequested();

            Set(key, value, options);
            return(CompletedTask);
        }
        public async Task SetAsync(string key, IOStream value, StreamCacheEntryOptions options, CancellationToken token = default)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            token.ThrowIfCancellationRequested();

            await ConnectAsync(token).ConfigureAwait(false);

            var creationTime       = DateTimeOffset.UtcNow;
            var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);

            //var result = await _cache.SetAsync(key, new MetadataStream<byte[][]>(value,
            //    new byte[][]
            //    {
            //        BitConverter.GetBytes(absoluteExpiration?.Ticks ?? NotPresent),
            //        BitConverter.GetBytes(options.SlidingExpiration?.Ticks ?? NotPresent),
            //    })).ConfigureAwait(false);
        }
        public void Set(string key, IOStream value, StreamCacheEntryOptions options)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            Connect();

            var creationTime       = DateTimeOffset.UtcNow;
            var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);

            //var result = _cache.Set(key, new MetadataStream<byte[][]>(value,
            //    new byte[][]
            //    {
            //        BitConverter.GetBytes(absoluteExpiration?.Ticks ?? NotPresent),
            //        BitConverter.GetBytes(options.SlidingExpiration?.Ticks ?? NotPresent),
            //    }));
        }