/// <summary>
        /// Removes an item from the cache by it's key asynchronously.
        /// </summary>
        /// <param name="key">The key for the cache item.</param>
        /// <param name="token">The <see cref="CancellationToken"/> for the operation.</param>
        public async Task RemoveAsync(string key, CancellationToken token = new CancellationToken())
        {
            token.ThrowIfCancellationRequested();
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var collection = await CollectionProvider.GetCollectionAsync().ConfigureAwait(false);

            await collection.RemoveAsync(key).ConfigureAwait(false);
        }
        /// <summary>
        /// Gets a cache item by its key asynchronously, returning null if the item does not exist within the Cache.
        /// </summary>
        /// <param name="key">The key to lookup the item.</param>
        /// <param name="token">The <see cref="CancellationToken"/> for the operation.</param>
        /// <returns>The cache item if found, otherwise null.</returns>
        public async Task <byte[]> GetAsync(string key, CancellationToken token = new CancellationToken())
        {
            token.ThrowIfCancellationRequested();
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var collection = await CollectionProvider.GetCollectionAsync().ConfigureAwait(false);

            var result = await collection.GetAsync(key, new GetOptions().Transcoder(_transcoder))
                         .ConfigureAwait(false);

            return(result.ContentAs <byte[]>());
        }
        /// <summary>
        /// Sets a cache item using its key asynchronously. If the key exists, it will not be updated.
        /// </summary>
        /// <param name="key">The key for the cache item.</param>
        /// <param name="value">An array of bytes representing the item.</param>
        /// <param name="options">The <see cref="DistributedCacheEntryOptions"/> for the item; note that only sliding expiration is currently supported.</param>
        /// <param name="token">The <see cref="CancellationToken"/> for the operation.</param>
        public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions?options,
                                   CancellationToken token = new CancellationToken())
        {
            token.ThrowIfCancellationRequested();
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            var collection = await CollectionProvider.GetCollectionAsync().ConfigureAwait(false);

            await collection.UpsertAsync(key, value, new UpsertOptions().Transcoder(_transcoder).Expiry(GetLifetime(options)))
            .ConfigureAwait(false);
        }
        /// <summary>
        /// Gets a cache item by its key asynchronously, returning null if the item does not exist within the Cache.
        /// </summary>
        /// <param name="key">The key to lookup the item.</param>
        /// <param name="token">The <see cref="CancellationToken"/> for the operation.</param>
        /// <returns>The cache item if found, otherwise null.</returns>
        async Task <byte[]> IDistributedCache.GetAsync(string key, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            var collection = await CollectionProvider.GetCollectionAsync().ConfigureAwait(false);

            try
            {
                var result = await collection.GetAsync(key, new GetOptions().Transcoder(_transcoder))
                             .ConfigureAwait(false);

                return(result.ContentAs <byte[]>());
            }
            catch (DocumentNotFoundException)
            {
                return(null);
            }
        }