CacheManager

Cache Library.NETC#Multi-layerDistributed CacheRedisASP.NET

GitHub Overview

MichaCo/CacheManager

CacheManager is an open source caching abstraction layer for .NET written in C#. It supports various cache providers and implements many advanced features.

Stars2,391
Watchers151
Forks454
Created:March 22, 2015
Language:C#
License:Apache License 2.0

Topics

c-sharpcachecachemanagercachingdotnetdotnet-corememcachedredis

Star History

MichaCo/CacheManager Star History
Data as of: 7/18/2025, 05:46 AM

Cache Library

CacheManager

Overview

CacheManager is an open-source cache abstraction layer for .NET written in C#, supporting multiple cache providers and implementing advanced caching features.

Details

CacheManager is a comprehensive caching solution designed to make .NET developers' lives easier and enable implementation of complex caching scenarios with just a few lines of code. The multi-layer caching feature allows placing in-process cache in front of distributed cache to speed up read access. It supports both sliding and absolute expiration, with expiration settings configurable per cache handle or per cache item. The cache region feature enables grouping elements and bulk deletion, even implementing this functionality when some cache systems don't support it natively. It offers rich features including statistics counters, event systems, and serialization configuration, and can integrate with various cache providers like Redis, Memcached, and Couchbase. Cross-platform support for .NET Core / ASP.NET Core enables operation on Windows, Linux, and macOS.

Advantages and Disadvantages

Advantages

  • Unified Interface: Handle different cache technologies with a single ICache
  • Multi-layer: Optimization through combination of in-process and distributed caches
  • Rich Features: Comprehensive functionality including expiration, regions, statistics, events
  • Cross-platform: .NET Standard support for Windows/Linux/macOS operation
  • Diverse Providers: Wide support for Redis, Memcached, Couchbase, and more
  • Configurable: Flexible serialization and cache policy configuration
  • Performance: Optimized performance and memory management

Disadvantages

  • .NET Only: Cannot be used from other languages/platforms
  • Complexity: Configuration and understanding complexity due to rich features
  • Overhead: Over-featured for simple caching use cases
  • Dependencies: Dependencies on multiple external libraries
  • Learning Curve: High learning cost due to multiple features
  • Debugging: Debugging complexity due to multi-layer structure

Key Links

Code Examples

Basic Cache Usage

using CacheManager.Core;

// Create simple in-memory cache
var cache = CacheFactory.New()
    .WithUpdateMode(CacheUpdateMode.Up)
    .WithSerializer(typeof(JsonCacheSerializer))
    .WithMicrosoftMemoryCaching()
    .Build();

// Store data
cache.Put("user:123", new { Name = "John", Age = 30 });

// Retrieve data
var user = cache.Get("user:123");
if (user != null)
{
    Console.WriteLine($"Cache hit: {user}");
}
else
{
    Console.WriteLine("Cache miss");
}

Multi-layer Cache Configuration

using CacheManager.Core;
using CacheManager.Microsoft.Extensions.Caching.Memory;
using CacheManager.Redis;

// Two-layer cache: In-memory + Redis
var cache = CacheFactory.New()
    .WithUpdateMode(CacheUpdateMode.Up)
    .WithMicrosoftMemoryCaching("memory")
    .WithRedisConfiguration("redis", config => {
        config.WithEndpoint("localhost", 6379);
        config.WithDatabase(0);
    })
    .WithRedisCaching("redis")
    .WithJsonSerializer()
    .Build();

// Data access (automatic tier management)
var result = cache.GetOrAdd("expensive-data", (key) => {
    // Heavy processing (DB access, etc.)
    return ComputeExpensiveData();
});

Using Expiration and Regions

// Expiration and region settings
cache.Put("session:abc123", sessionData, TimeSpan.FromMinutes(30));

// Logical grouping using regions
cache.Put("user-data", "user:123", userData, "users");
cache.Put("user-prefs", "pref:123", preferences, "users");

// Region-based deletion
cache.ClearRegion("users");

// Sliding expiration
cache.Put("activity", activityData, ExpirationMode.Sliding, TimeSpan.FromMinutes(15));

Dependency Injection in ASP.NET Core

// Startup.cs or Program.cs
using CacheManager.Core;
using CacheManager.Microsoft.Extensions.DependencyInjection;

public void ConfigureServices(IServiceCollection services)
{
    // CacheManager configuration
    services.AddCacheManager(builder =>
        builder.WithUpdateMode(CacheUpdateMode.Up)
               .WithMicrosoftMemoryCaching()
               .WithRedisConfiguration("redis", config => {
                   config.WithEndpoint("localhost", 6379);
               })
               .WithRedisCaching("redis")
               .WithJsonSerializer()
    );
}

// Usage in controller
[ApiController]
public class UserController : ControllerBase
{
    private readonly ICacheManager _cache;
    
    public UserController(ICacheManager cache)
    {
        _cache = cache;
    }
    
    [HttpGet("{id}")]
    public async Task<User> GetUser(int id)
    {
        return await _cache.GetOrAddAsync($"user:{id}", async (key) => {
            return await _userRepository.GetByIdAsync(id);
        }, TimeSpan.FromMinutes(10));
    }
}

Statistics and Event Handling

// Enable statistics
var cache = CacheFactory.New()
    .WithMicrosoftMemoryCaching()
    .EnableStatistics()
    .Build();

// Register event handlers
cache.OnAdd += (sender, args) => {
    Console.WriteLine($"Item added: {args.Key}");
};

cache.OnGet += (sender, args) => {
    Console.WriteLine($"Item retrieved: {args.Key}");
};

cache.OnRemove += (sender, args) => {
    Console.WriteLine($"Item removed: {args.Key}, Reason: {args.Reason}");
};

// Check statistics after multiple accesses
for (int i = 0; i < 100; i++)
{
    cache.GetOrAdd($"item:{i}", i);
}

var stats = cache.Statistics;
Console.WriteLine($"Hit ratio: {stats.Ratio:P2}");
Console.WriteLine($"Items: {stats.Items}");
Console.WriteLine($"Hits: {stats.Hits}");
Console.WriteLine($"Misses: {stats.Misses}");

Custom Serialization

using CacheManager.Serialization.Json;
using Newtonsoft.Json;

// Custom JSON configuration
var cache = CacheFactory.New()
    .WithMicrosoftMemoryCaching()
    .WithSerializer(typeof(JsonCacheSerializer), new JsonSerializerSettings
    {
        DateTimeZoneHandling = DateTimeZoneHandling.Utc,
        NullValueHandling = NullValueHandling.Ignore
    })
    .Build();

// Caching complex objects
public class ComplexData
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedAt { get; set; }
    public List<string> Tags { get; set; }
}

var complexData = new ComplexData
{
    Id = 1,
    Name = "Sample Data",
    CreatedAt = DateTime.UtcNow,
    Tags = new List<string> { "tag1", "tag2", "tag3" }
};

cache.Put("complex:1", complexData, TimeSpan.FromHours(1));

Conditional Cache Updates

// Cache with data version management
public class CacheService
{
    private readonly ICacheManager _cache;
    
    public CacheService(ICacheManager cache)
    {
        _cache = cache;
    }
    
    public async Task<T> GetWithVersionCheck<T>(string key, Func<Task<(T Data, string Version)>> factory)
    {
        var cacheKey = $"data:{key}";
        var versionKey = $"version:{key}";
        
        var cachedData = _cache.Get<T>(cacheKey);
        var cachedVersion = _cache.Get<string>(versionKey);
        
        // Check latest version
        var (currentData, currentVersion) = await factory();
        
        if (cachedData != null && cachedVersion == currentVersion)
        {
            return cachedData;
        }
        
        // Update cache
        _cache.Put(cacheKey, currentData, TimeSpan.FromMinutes(30));
        _cache.Put(versionKey, currentVersion, TimeSpan.FromMinutes(30));
        
        return currentData;
    }
}

// Usage example
var data = await cacheService.GetWithVersionCheck("user-settings", async () => {
    var settings = await _database.GetUserSettingsAsync(userId);
    var version = settings.LastModified.ToString("O");
    return (settings, version);
});