Advanced thread-safe generic wrapper for System.Runtime.Caching with comprehensive features including cache groups, dependency management, automatic population, and persistent disk storage. Key Features: • Cache groups for organized data management • Dependency relationships between cache groups • Automatic cache population with custom methods • Persistent cache storage that survives application restarts • Retrieve all items from a group with GetAllByGroup() • Comprehensive metadata and monitoring with GetAllCacheMetadata() • Detailed statistics and disk usage analysis • Multiple expiration strategies (sliding/absolute) • Auto-refresh with configurable intervals • Thread-safe operations with minimal lock contention • JSON-based serialization for persistent storage Perfect for high-performance applications requiring sophisticated caching patterns, data persistence, and comprehensive monitoring capabilities.
$ dotnet add package CacheUtilityA thread-safe, generic wrapper for System.Runtime.Caching that simplifies cache access and supports powerful caching patterns.
CacheUtility provides an easy-to-use abstraction over the standard .NET memory cache with additional features:
The most common pattern is to request an item from the cache, providing a function to generate the item if it doesn't exist:
// Basic usage with default 30-minute sliding expiration
var result = CacheUtility.Get("MyKey", "MyGroupName", () =>
{
return MyLongRunningTask();
});
// With custom sliding expiration
var result = CacheUtility.Get("MyKey", "MyGroupName", TimeSpan.FromHours(1), () =>
{
return MyLongRunningTask();
});
// With absolute expiration
var result = CacheUtility.Get("MyKey", "MyGroupName", DateTime.Now.AddDays(1), () =>
{
return MyLongRunningTask();
});
// With full customization
var result = CacheUtility.Get("MyKey", "MyGroupName",
DateTime.Now.AddDays(1), // Absolute expiration
TimeSpan.FromMinutes(10), // Sliding expiration
CacheItemPriority.Default, // Priority
() => MyLongRunningTask());
For async operations, you can use the utility with async/await:
var result = await CacheUtility.Get("MyKey", "MyGroupName", async () =>
{
return await MyLongRunningTaskAsync();
});
Get all cached items that belong to a specific group:
var allItems = CacheUtility.GetAllByGroup("MyGroupName");
// Iterate through all items in the group
foreach (var kvp in allItems)
{
Console.WriteLine($"Key: {kvp.Key}, Value: {kvp.Value}");
}
// Access specific items if you know the key
if (allItems.ContainsKey("MySpecificKey"))
{
var specificItem = allItems["MySpecificKey"];
}
Remove a specific item from the cache:
CacheUtility.Remove("MyKey", "MyGroupName");Remove multiple items that contain specific strings:
CacheUtility.Remove(new List<string> { "UserProfile", "123" }, "UserData");
// This will remove any cache key containing both "UserProfile" and "123"Remove an entire group of cached items:
CacheUtility.RemoveGroup("MyGroupName");Remove multiple groups:
CacheUtility.RemoveGroup("GroupA", "GroupB", "GroupC");Set up dependencies between cache groups so that when one group is cleared, its dependent groups are also cleared:
// Set up dependencies
CacheUtility.SetDependencies("ParentGroup", "ChildGroup1", "ChildGroup2");
// Now when ParentGroup is removed, ChildGroup1 and ChildGroup2 will also be removed
CacheUtility.RemoveGroup("ParentGroup");Clear the entire cache:
CacheUtility.RemoveAll();Clear the cache except for specific groups:
CacheUtility.RemoveAllButThese(new List<string> { "CriticalData", "ApplicationSettings" });// Cache user data with a sliding expiration
var userData = CacheUtility.Get($"User_{userId}", "UserProfiles", TimeSpan.FromMinutes(30), () =>
{
return database.GetUserById(userId);
});// Cache application settings with absolute expiration
var settings = CacheUtility.Get("GlobalSettings", "AppConfig", DateTime.Now.AddHours(12), () =>
{
return configurationService.LoadSettings();
});// Set up dependencies
CacheUtility.SetDependencies("UserData", "UserProfiles", "UserPreferences", "UserActivity");
CacheUtility.SetDependencies("UserProfiles", "ProfilePhotos");
// Now when UserData is cleared, all dependent caches are also cleared
CacheUtility.RemoveGroup("UserData");
// This will clear UserData, UserProfiles, ProfilePhotos, UserPreferences, and UserActivity// Cache some user data
CacheUtility.Get("User1", "UserData", () => GetUserInfo(1));
CacheUtility.Get("User2", "UserData", () => GetUserInfo(2));
CacheUtility.Get("User3", "UserData", () => GetUserInfo(3));
// Get all cached items from the group
var allUsers = CacheUtility.GetAllByGroup("UserData");
Console.WriteLine($"Found {allUsers.Count} cached users");
// Process each cached item
foreach (var user in allUsers)
{
Console.WriteLine($"User Key: {user.Key}, Data: {user.Value}");
}The CacheUtility is built on top of .NET's MemoryCache, which has built-in memory pressure detection. However, be mindful of:
All operations in CacheUtility are thread-safe. The implementation uses ReaderWriterLockSlim for efficient concurrent access and CacheLock for synchronizing modifications to the cache.