Open.Caching.Memory 3.0.1

.NET Standard 2.0
dotnet add package Open.Caching.Memory --version 3.0.1
NuGet\Install-Package Open.Caching.Memory -Version 3.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Open.Caching.Memory" Version="3.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Open.Caching.Memory --version 3.0.1
#r "nuget: Open.Caching.Memory, 3.0.1"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install Open.Caching.Memory as a Cake Addin
#addin nuget:?package=Open.Caching.Memory&version=3.0.1

// Install Open.Caching.Memory as a Cake Tool
#tool nuget:?package=Open.Caching.Memory&version=3.0.1

Open.Caching

GitHub license 100% code coverage

Useful set of DI/IoC agnostic interfaces, utilities and extensions for simplifying cache usage.

Implementation

With the following libraries, you can build other libraries that sever their dependency from any cache and allow you to inject whichever you want.


Core Interfaces & Extensions

Open.Caching

https://www.nuget.org/packages/Open.Caching
NuGet Core package for interfaces and base classes.

Library/Vendor Specific Implementations

Open.Caching.Memory

https://www.nuget.org/packages/Open.Caching.Memory
NuGet Contains MemoryCacheAdapter for use with any IMemoryCache.

Open.Caching.Runtime

https://www.nuget.org/packages/Open.Caching.Runtime
NuGet Contains ObjectCacheAdapter for use with any System.Runtime.Caching.ObjectCache.

Open.Caching.Web

https://www.nuget.org/packages/Open.Caching.Web
NuGet Contains WebCacheAdapter for use with any System.Web.Caching.Cache.
Useful when attempting to transition code away from legacy ASP.NET.


Notable Similarities & Differences

The above adapters all accept strings as keys, but only MemoryCacheAdapter will accept any type of key as IMemoryCache uses objects as keys. If your dependency injection configuration uses ICacheAdapter<string> as its cache interface then any of the implementations can be used. So if you are transitioning from a legacy ASP.NET environment, switching to MemoryCacheAdapter<string> will make things easy.

Every cache implementation listed handles absolute and sliding expiration.

Because IMemoryCache allows for null values to be inserted, the other implementations use a placeholder NullValue to indicate null and retain parity for all implementations.

Not Yet Supported

Some of the reasons for not supporting certain features should be obvious.
The intention of these utilities is to cover the 95%+ use case.
Setting expiration is very common, but setting priority is not so common.

  • At this time, 'priority' is not supported as each cache has a slightly different implementation.
  • Eviction call backs, cache item or file system watchers.

Interfaces, Classes, & Structs

ICacheAdapter<TKey>

Modeled after Microsoft.Extensions.Caching.Memory.IMemoryCache, this interface facilitates cache access for all adapters and extensions.

namespace Open.Caching;

public interface ICacheAdapter<TKey>
{
	bool TryGetValue<TValue>(
		TKey key,
		out TValue item,
		bool throwIfUnexpectedType = false);

	void Set<TValue>(TKey key, TValue item);

	void Remove(TKey key);
}

It does not offer a mechanism for a cache policy as that is provided by CacheAdapterBase<TKey, TCache>.

ExpirationPolicy

This read only struct combines both .Absolute and .Sliding expirations into TimeSpan values.

.Absolute is a TimeSpan as it is almost always the case that expiration happens relative from when the cache entry was inserted.

DateTimeOffset AbsoluteRelativeToNow is derived from the value of .Absolute and the DateTimeOffset.Now

ICachePolicyProvider<TKey, TPolicy>

This interface allows for returning a specific ICacheAdapter<TKey that will default to that policy.

CacheAdapterBase<TKey, TCache>

Every adapter derives from this base class and implements the ICachePolicyProvider<TKey, ExpirationPolicy> interface. Allowing for simple or policy driven cache access.


CacheItem<TKey, TValue>

The intention of this and the following classes is to simplify access to a cached resource.
Much like a Lazy<T>, or any other container class, you can affix, or pass around these classes without the consumer having to know what the key is.

public class MyClass {

    // Injected ICacheAdapter<string>.
    public MyClass(ICacheAdapter<string> cache)
    {
        // The key is defined in only one place.
        _value = cache
            .CreateItem(
                key: "a cache key",
                defaultValue: "[not set]");
    }

    readonly CacheItem<string, string> _value;
    public string Value {
        get => _value; // Implicit
        set => _value.Value = value;
    }
}

LazyCacheItem<TKey, TValue>

The important idea here is to allow for the insertion of a Lazy<T> so that any subsequent requests to that resource either wait for it to complete, or receive the already resolved value.

The underlying .GetOrCreateLazy<T> extension properly evicts the Lazy<T> if the Value property throws an exception.

public class MyClass {

    // Injected ICacheAdapter<string>.
    public MyClass(ICacheAdapter<string> cache)
    {
        // The key is defined in only one place.
        _value = cache
            .CreateLazyItem(
                key: "a cache key",
                ()=>{
                /* long running process. */
                });
    }

    public string Value => _value; // Implicit
}

AsyncLazyCacheItem<TKey, TValue>

This class implements IAsyncCacheItem<TValue> and therefore is awaitable.

Similar to the above, the underlying .GetOrCreateLazyAsync method uses a Lazy<Task<T>>> to initialize the method and asynchronously produce a result. Any exceptions thrown by the the Task<T> or its factory method will evict the entry from the cache.

public class MyClass {

    // Injected ICacheAdapter<string>.
    public MyClass(ICacheAdapter<string> cache)
    {
        // The key is defined in only one place.
        _value = cache
            .CreateAsyncLazyItem(
                key: "a cache key",
                async ()=>{
                /* long running async process. */
                });
    }

    public Task<string> Value => _value; // Implicit
}
Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48 net481
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.1 731 3/9/2022
3.0.0 224 3/9/2022
3.0.0-alpha 75 3/6/2022