SplatDev.Cache 1.0.3

dotnet add package SplatDev.Cache --version 1.0.3
                    
NuGet\Install-Package SplatDev.Cache -Version 1.0.3
                    
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="SplatDev.Cache" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SplatDev.Cache" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="SplatDev.Cache" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SplatDev.Cache --version 1.0.3
                    
#r "nuget: SplatDev.Cache, 1.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SplatDev.Cache@1.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SplatDev.Cache&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=SplatDev.Cache&version=1.0.3
                    
Install as a Cake Tool

SplatDev.Cache

Generic caching abstractions for SplatDev packages — provider-agnostic interfaces for Redis, HybridCache, MemoryCache, and other backends.

NuGet License: MIT

Compatibility

.NET Umbraco Package Version
8.0 13 1.0.0
10.0 17 1.0.0

Installation

dotnet add package SplatDev.Cache

This package has zero external dependencies — it defines only abstractions.

Interfaces

ICacheProvider

The core abstraction for pluggable cache backends:

public interface ICacheProvider
{
    T? Get<T>(string key);
    Task<T?> GetAsync<T>(string key, CancellationToken cancellationToken = default);

    void Set<T>(string key, T value, CacheEntryOptions? options = null);
    Task SetAsync<T>(string key, T value, CacheEntryOptions? options = null, CancellationToken cancellationToken = default);

    T? GetOrCreate<T>(string key, Func<T> factory, CacheEntryOptions? options = null);
    Task<T?> GetOrCreateAsync<T>(string key, Func<CancellationToken, Task<T>> factory,
        CacheEntryOptions? options = null, CancellationToken cancellationToken = default);

    void Remove(string key);
    Task RemoveAsync(string key, CancellationToken cancellationToken = default);

    Task<bool> ExistsAsync(string key, CancellationToken cancellationToken = default);
    Task<bool> RemoveByPatternAsync(string pattern, CancellationToken cancellationToken = default);
    Task<bool> RemoveByTagAsync(string tag, CancellationToken cancellationToken = default);
}

RemoveByPatternAsync and RemoveByTagAsync are optional — adapters that cannot support these operations may throw NotSupportedException.

ICacheKeyBuilder

Canonical key composition for cache entries:

public interface ICacheKeyBuilder
{
    string Build(params string[] segments);
    string BuildPattern(params string[] segments);
}

Default key format: {KeyPrefix}:segment1:segment2:...

IDistributedLock

Distributed lock abstraction for coordinated cache operations:

public interface IDistributedLock
{
    Task<LockResult> AcquireAsync(
        string resource,
        TimeSpan timeout,
        TimeSpan? autoRelease = null,
        CancellationToken cancellationToken = default);
}

ICacheSerializer

Pluggable serialization for cache values:

public interface ICacheSerializer
{
    byte[]? Serialize<T>(T? value);
    T? Deserialize<T>(byte[]? data);
}

Models

CacheOptions

public class CacheOptions
{
    public string KeyPrefix { get; set; } = "";
    public TimeSpan DefaultTtl { get; set; } = TimeSpan.FromMinutes(30);
    public string KeySeparator { get; set; } = ":";
}

Bound from IConfiguration section "SplatDev:Cache".

CacheEntryOptions

public class CacheEntryOptions
{
    public TimeSpan? AbsoluteExpiration { get; set; }
    public TimeSpan? SlidingExpiration { get; set; }

    public static CacheEntryOptions WithAbsoluteExpiration(TimeSpan duration);
    public static CacheEntryOptions WithSlidingExpiration(TimeSpan duration);
}

CacheEntry<T>

public record CacheEntry<T>(string Key, T Value, DateTimeOffset? ExpiresAt = null);

LockResult

public sealed class LockResult
{
    public bool Acquired { get; init; }
    public string Resource { get; init; }
    public IDisposable? Handle { get; init; }
}

Helpers

CacheKeyBuilder

Default implementation of ICacheKeyBuilder. Composes keys in "splatdev:<app>:<domain>:<id>" format using the configured KeyPrefix and KeySeparator.

PatternMatcher

Glob-to-regex utility for cache key pattern matching:

public static class PatternMatcher
{
    public static Regex GlobToRegex(string pattern, bool caseInsensitive = true);
    public static bool IsMatch(string input, string pattern, bool caseInsensitive = true);
}

SystemTextJsonCacheSerializer

Default implementation of ICacheSerializer using System.Text.Json with camelCase naming policy.

CacheStampedeGuard

Per-key SemaphoreSlim stampede protection for GetOrCreateAsync patterns. Registered as a singleton via the DI extension.

public sealed class CacheStampedeGuard
{
    public Task<T?> GetOrCreateWithStampedeProtectionAsync<T>(
        string key,
        Func<CancellationToken, Task<T>> factory,
        Func<string, CancellationToken, Task<T?>> getAsync,
        Func<string, T, CacheEntryOptions?, CancellationToken, Task> setAsync,
        CacheEntryOptions? options = null,
        CancellationToken cancellationToken = default);
}

Dependency Injection

Register all abstractions in one call:

services.AddSplatDevCacheAbstractions(configuration);

This binds CacheOptions from "SplatDev:Cache" config section and registers:

  • CacheOptions (singleton)
  • ICacheKeyBuilderCacheKeyBuilder (singleton)
  • ICacheSerializerSystemTextJsonCacheSerializer (singleton)
  • CacheStampedeGuard (singleton)

Note: ICacheProvider is NOT registered — you must add a provider package (e.g. SplatDev.Cache.Redis or SplatDev.Cache.Hybrid).

Configuration

{
  "SplatDev": {
    "Cache": {
      "KeyPrefix": "myapp",
      "DefaultTtl": "00:10:00",
      "KeySeparator": ":"
    }
  }
}

Available provider implementations

Package Backend Description
SplatDev.Cache.Redis StackExchange.Redis Distributed Redis cache
SplatDev.Cache.Hybrid .NET HybridCache L1/L2 hybrid with stampede protection (.NET 10+)

Design decisions

  • Stampede protection: Built into the foundation layer via per-key SemaphoreSlim (CacheStampedeGuard). Provider adapters may override with distributed locking.
  • Tag-based invalidation: First-class in ICacheProvider. Adapters that cannot support it throw NotSupportedException.
  • Serializer scope: Global default (ICacheSerializer) with per-call override support.
  • Cancellation semantics: Cancellation token cancels the running factory in GetOrCreateAsync.

Dependencies

None. This package has zero NuGet dependencies — it is pure interface and model definitions.


SplatDev.Cache — part of the SplatDev.Umbraco.Plugins suite. Licensed under MIT. © SplatDev Ltda.

Changelog

1.0.3 — 2026-08-24

Removes a dashboard screenshot that showed an error toast. It was captured against a site where this plugin's API was unreachable, so it advertised a broken dashboard. No screenshot is better than a misleading one; a replacement will be taken against a working install.

1.0.2 — 2026-08-24

Package metadata only: the listing now carries an icon and search tags, and the project and repository links point at the organisation that actually hosts this code. No code changes.

1.0.1 — 2026-08-24

This package now keeps a changelog. Earlier releases predate it and are not reconstructed here — consult the repository history for those. From this version on, every release records what changed for someone using it.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on SplatDev.Cache:

Package Downloads
SplatDev.Umbraco.Plugins.CacheManager

Umbraco cache manager/warmer plugin supporting Umbraco 13 (net8.0) and Umbraco 17 (net10.0)

SplatDev.Cache.Hybrid

Microsoft.Extensions.Caching.Hybrid (HybridCache) adapter for SplatDev.Cache abstractions. L1/L2 caching with stampede protection — .NET 10+.

SplatDev.Cache.Redis

StackExchange.Redis adapter for SplatDev.Cache abstractions. Distributed caching with connection multiplexing.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.3 51 8/24/2026