ItemsCache.Refresh.Polling.Metrics
0.0.1-preview.18
dotnet add package ItemsCache.Refresh.Polling.Metrics --version 0.0.1-preview.18
NuGet\Install-Package ItemsCache.Refresh.Polling.Metrics -Version 0.0.1-preview.18
<PackageReference Include="ItemsCache.Refresh.Polling.Metrics" Version="0.0.1-preview.18" />
<PackageVersion Include="ItemsCache.Refresh.Polling.Metrics" Version="0.0.1-preview.18" />
<PackageReference Include="ItemsCache.Refresh.Polling.Metrics" />
paket add ItemsCache.Refresh.Polling.Metrics --version 0.0.1-preview.18
#r "nuget: ItemsCache.Refresh.Polling.Metrics, 0.0.1-preview.18"
#:package ItemsCache.Refresh.Polling.Metrics@0.0.1-preview.18
#addin nuget:?package=ItemsCache.Refresh.Polling.Metrics&version=0.0.1-preview.18&prerelease
#tool nuget:?package=ItemsCache.Refresh.Polling.Metrics&version=0.0.1-preview.18&prerelease
ItemsCache
A high-performance, flexible caching library for ASP.NET Core applications that provides automatic data loading, background refresh, and retry logic with SOLID principles.
Features
- 🚀 High Performance: Optimized for speed with minimal memory overhead
- 🔄 Background Refresh: Automatic cache refresh with configurable intervals
- 🛡️ Retry Logic: Built-in retry policies using Polly for resilient operations
- 🏗️ SOLID Principles: Clean architecture with proper abstractions
- 📦 Modular Design: Use only what you need with separate packages
- 🔧 Easy Integration: Simple setup with dependency injection
- 📊 Observability: Built-in logging and monitoring support
Packages
Quick Start
Installation
For the complete experience, install the main package:
dotnet add package ItemsCache.All
Or install individual packages based on your needs:
dotnet add package ItemsCache
dotnet add package ItemsCache.Refresh.Polling
dotnet add package ItemsCache.RetryPolicy
Basic Usage
- Register services in your
Program.cs:
using ItemsCache.Core.Abstraction.Interfaces;
using ItemsCache.Core.Extensions;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add database context (example with Entity Framework Core)
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
// Register ItemsCache service
builder.Services.AddItemsCache<int, Product>();
// Register your data source
builder.Services.AddScoped<IDataSource<int, Product>, DataFromDbSource>();
var app = builder.Build();
- Create a data source implementing
IDataSource<TKey, TCacheItem>:
using ItemsCache.Core.Abstraction.Interfaces;
using Microsoft.EntityFrameworkCore;
public class DataFromDbSource : IDataSource<int, Product>
{
private readonly AppDbContext _dbContext;
public DataFromDbSource(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IEnumerable<KeyValuePair<int, Product>>> LoadAllAsync(
CancellationToken cancellationToken = default)
{
var products = await _dbContext.Set<Product>().ToListAsync(cancellationToken);
return products.ToDictionary(p => p.Id);
}
}
- Use the cache service in your controllers:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IItemsCacheService<int, Product> _productItemsCache;
public ProductsController(IItemsCacheService<int, Product> productItemsCache)
{
_productItemsCache = productItemsCache;
}
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(int id)
{
if (_productItemsCache.TryGetByKey(id, out var product))
{
return Ok(product);
}
return NotFound($"Product with ID {id} not found");
}
[HttpGet]
public ActionResult<IEnumerable<Product>> GetAllProducts()
{
var products = _productItemsCache.GetAll().ToDictionary();
return Ok(products.Values);
}
}
Complete Example
This example demonstrates a complete setup with all features: basic cache, grouped cache, polling refresh, and metrics.
Step 1: Define Your Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public decimal Price { get; set; }
public string? Category { get; set; }
public bool IsActive { get; set; } = true;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
public DateTime? DeletedAt { get; set; }
}
Step 2: Configure appsettings.json
{
"CacheOptions": {
"RefreshInterval": "00:00:30"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"ItemsCache": "Information"
}
}
}
Step 3: Complete Program.cs Setup
using ItemsCache.Core.Abstraction.Interfaces;
using ItemsCache.Core.Extensions;
using ItemsCache.Core.Metrics.Extensions;
using ItemsCache.Refresh.Polling.Extensions;
using ItemsCache.Refresh.Polling.Metrics.Extensions;
using Microsoft.EntityFrameworkCore;
using Prometheus;
using SampleApi.Data;
using SampleApi.Models;
using SampleApi.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Database setup
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseInMemoryDatabase("InMemoryDb"));
// Register ItemsCache service
builder.Services.AddItemsCache<int, Product>();
// Register grouped cache services
builder.Services.AddItemsCacheGrouped<int, Product, string>(p => p.Category ?? "Uncategorized");
builder.Services.AddItemsCacheGrouped<int, Product, bool>(p => p.IsActive);
// Register Prometheus metrics (optional)
var prometheusRecorder = new PrometheusMetricsRecorder<int, Product>();
builder.Services.AddItemsCacheMetrics<int, Product>(prometheusRecorder);
builder.Services.AddItemsCacheGroupedMetrics<int, Product, string>();
builder.Services.AddItemsCacheGroupedMetrics<int, Product, bool>();
// Register data source
builder.Services.AddScoped<IDataSource<int, Product>, DataFromDbSource>();
// Register polling refresh (optional)
builder.Services.AddPollingRefreshItemCacheHandler<int, Product, RefreshContext>(builder.Configuration);
builder.Services.AddPollingRefreshMetrics<int, Product, RefreshContext>();
// Register refresh data source
builder.Services.AddScoped<IDataSourceWithRefresh<int, Product, RefreshContext>,
DataFromDbSourceWithRefresh>();
var app = builder.Build();
// Configure Prometheus metrics endpoint
app.UseHttpMetrics();
app.MapMetrics();
app.MapControllers();
// Seed database (example)
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
context.Database.EnsureCreated();
// Seed your data here
}
app.Run();
Step 4: Implement Data Source with Refresh
For polling refresh, implement IDataSourceWithRefresh:
using ItemsCache.Refresh.Abstraction.Models;
using ItemsCache.Refresh.Polling.Abstraction.Interfaces;
using ItemsCache.Refresh.Polling.Abstraction.Models;
using Microsoft.EntityFrameworkCore;
public class DataFromDbSourceWithRefresh : IDataSourceWithRefresh<int, Product, RefreshContext>
{
private readonly AppDbContext _dbContext;
public DataFromDbSourceWithRefresh(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<CacheItemRefreshResult<int, Product, RefreshContext>> GetUpdatedItemsAsync(
RefreshContext? lastRefreshContext,
CancellationToken cancellationToken = default)
{
var lastRefreshTime = lastRefreshContext?.LastRefresh ?? DateTime.MinValue;
var updatedTime = DateTime.UtcNow;
var updatedItems = await _dbContext.Products
.Where(p => p.UpdatedAt > lastRefreshTime ||
(p.DeletedAt != null && p.DeletedAt > lastRefreshTime))
.ToListAsync(cancellationToken);
var newRefreshContext = new RefreshContext
{
LastRefresh = updatedTime
};
var cacheItems = updatedItems
.Select(item => new RefreshCacheItem<int, Product>(
item.Id,
item,
item.DeletedAt != null ? RefreshCacheItemStatus.Deleted : RefreshCacheItemStatus.Updated))
.ToList();
return new CacheItemRefreshResult<int, Product, RefreshContext>(
cacheItems,
newRefreshContext);
}
}
// RefreshContext model
public class RefreshContext
{
public DateTime LastRefresh { get; set; }
}
Advanced Configuration
Background Refresh
ItemsCache supports automatic cache refresh using polling. The cache periodically checks for updated items and refreshes them automatically.
Configuration
Configure polling refresh in appsettings.json:
{
"CacheOptions": {
"RefreshInterval": "00:00:30"
}
}
The RefreshInterval is specified as a TimeSpan string (HH:mm:ss format). The default is 30 seconds.
Register Polling Refresh
using ItemsCache.Refresh.Polling.Extensions;
// Register polling refresh handler
builder.Services.AddPollingRefreshItemCacheHandler<int, Product, RefreshContext>(
builder.Configuration);
// Register your refresh data source
builder.Services.AddScoped<IDataSourceWithRefresh<int, Product, RefreshContext>,
DataFromDbSourceWithRefresh>();
Implement IDataSourceWithRefresh
To enable refresh, implement IDataSourceWithRefresh<TKey, TCacheItem, TRefreshContext>:
public class DataFromDbSourceWithRefresh : IDataSourceWithRefresh<int, Product, RefreshContext>
{
private readonly AppDbContext _dbContext;
public DataFromDbSourceWithRefresh(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<CacheItemRefreshResult<int, Product, RefreshContext>> GetUpdatedItemsAsync(
RefreshContext? lastRefreshContext,
CancellationToken cancellationToken = default)
{
// Get the last refresh time from context
var lastRefreshTime = lastRefreshContext?.LastRefresh ?? DateTime.MinValue;
// Set current time before querying to avoid missing updates
var updatedTime = DateTime.UtcNow;
// Query for items updated or deleted since last refresh
var updatedItems = await _dbContext.Products
.Where(p => p.UpdatedAt > lastRefreshTime ||
(p.DeletedAt != null && p.DeletedAt > lastRefreshTime))
.ToListAsync(cancellationToken);
// Create new refresh context with current time
var newRefreshContext = new RefreshContext
{
LastRefresh = updatedTime
};
// Map items to refresh cache items
var cacheItems = updatedItems
.Select(item => new RefreshCacheItem<int, Product>(
item.Id,
item,
item.DeletedAt != null ? RefreshCacheItemStatus.Deleted : RefreshCacheItemStatus.Updated))
.ToList();
return new CacheItemRefreshResult<int, Product, RefreshContext>(
cacheItems,
newRefreshContext);
}
}
RefreshContext
The RefreshContext is used to track the state of the last refresh. It's passed between refresh cycles:
public class RefreshContext
{
public DateTime LastRefresh { get; set; }
}
How It Works
- The polling service runs in the background at the configured interval
- On each cycle, it calls
GetUpdatedItemsAsyncwith the previousRefreshContext - Your implementation queries for items changed since the last refresh
- Updated items are automatically refreshed in the cache
- Deleted items are removed from the cache
- The new
RefreshContextis stored for the next cycle
Metrics
Add metrics for polling refresh:
using ItemsCache.Refresh.Polling.Metrics.Extensions;
builder.Services.AddPollingRefreshMetrics<int, Product, RefreshContext>();
Retry Policies
Configure retry behavior:
builder.Services.AddItemsCache()
.AddRetryPolicy(options =>
{
options.MaxRetryAttempts = 3;
options.DelayBetweenRetries = TimeSpan.FromSeconds(1);
options.UseExponentialBackoff = true;
});
Metrics Integration
ItemsCache provides built-in support for metrics recording. You can implement your own metrics recorder or use the provided Prometheus integration.
Prometheus Metrics Setup
- Install Prometheus package:
dotnet add package prometheus-net.AspNetCore
- Create a custom metrics recorder:
using ItemsCache.Core.Abstraction.Interfaces;
using Prometheus;
public class PrometheusMetricsRecorder<TKey, TCacheItem> : IMetricsRecorder<TKey, TCacheItem>
where TKey : notnull
where TCacheItem : class
{
private static readonly Counter CacheHits = Metrics
.CreateCounter("itemscache_cache_hits_total", "Total number of cache hits",
new[] { "cache_type" });
private static readonly Counter CacheMisses = Metrics
.CreateCounter("itemscache_cache_misses_total", "Total number of cache misses",
new[] { "cache_type" });
private static readonly Histogram CacheLoadDuration = Metrics
.CreateHistogram("itemscache_cache_load_duration_seconds",
"Duration of cache load operations in seconds",
new[] { "cache_type", "success" });
private static readonly Gauge CacheSize = Metrics
.CreateGauge("itemscache_cache_size", "Current cache size",
new[] { "cache_type" });
private readonly string _cacheTypeName;
public PrometheusMetricsRecorder()
{
_cacheTypeName = typeof(TCacheItem).Name;
}
public void RecordCacheHit(TKey key)
{
CacheHits.WithLabels(_cacheTypeName).Inc();
}
public void RecordCacheMiss(TKey key)
{
CacheMisses.WithLabels(_cacheTypeName).Inc();
}
public void RecordCacheLoad(TimeSpan duration, int itemCount, bool success)
{
CacheLoadDuration
.WithLabels(_cacheTypeName, success.ToString().ToLowerInvariant())
.Observe(duration.TotalSeconds);
}
public void RecordCacheSize(int count)
{
CacheSize.WithLabels(_cacheTypeName).Set(count);
}
// Implement other IMetricsRecorder methods...
}
- Register metrics in Program.cs:
using ItemsCache.Core.Metrics.Extensions;
using ItemsCache.Refresh.Polling.Metrics.Extensions;
using Prometheus;
// Register cache metrics
var prometheusRecorder = new PrometheusMetricsRecorder<int, Product>();
builder.Services.AddItemsCacheMetrics<int, Product>(prometheusRecorder);
// Register grouped cache metrics
builder.Services.AddItemsCacheGroupedMetrics<int, Product, string>();
builder.Services.AddItemsCacheGroupedMetrics<int, Product, bool>();
// Register polling refresh metrics
builder.Services.AddPollingRefreshMetrics<int, Product, RefreshContext>();
var app = builder.Build();
// Configure Prometheus metrics endpoint
app.UseHttpMetrics();
app.MapMetrics();
- Access metrics:
Once configured, metrics are available at /metrics endpoint. The following metrics are recorded:
itemscache_cache_hits_total- Total cache hitsitemscache_cache_misses_total- Total cache missesitemscache_cache_load_duration_seconds- Cache load operation durationitemscache_cache_refresh_duration_seconds- Cache refresh operation durationitemscache_item_updates_total- Total item updatesitemscache_item_deletions_total- Total item deletionsitemscache_cache_size- Current cache sizeitemscache_grouped_operations_total- Grouped cache operations
Custom Metrics Recorder
You can implement IMetricsRecorder<TKey, TCacheItem> to integrate with any metrics system:
public class CustomMetricsRecorder<TKey, TCacheItem> : IMetricsRecorder<TKey, TCacheItem>
where TKey : notnull
where TCacheItem : class
{
public void RecordCacheHit(TKey key) { /* Your implementation */ }
public void RecordCacheMiss(TKey key) { /* Your implementation */ }
public void RecordCacheLoad(TimeSpan duration, int itemCount, bool success) { /* ... */ }
// Implement other methods...
}
Custom Data Sources
Implement IDataSource<TKey, TCacheItem> to load data from any source. The LoadAllAsync method should return all items that will be cached.
Database Data Source Example
using ItemsCache.Core.Abstraction.Interfaces;
using Microsoft.EntityFrameworkCore;
public class DataFromDbSource : IDataSource<int, Product>
{
private readonly AppDbContext _dbContext;
public DataFromDbSource(AppDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<IEnumerable<KeyValuePair<int, Product>>> LoadAllAsync(
CancellationToken cancellationToken = default)
{
var products = await _dbContext.Set<Product>().ToListAsync(cancellationToken);
return products.ToDictionary(p => p.Id);
}
}
HTTP API Data Source Example
using ItemsCache.Core.Abstraction.Interfaces;
using System.Net.Http.Json;
public class ApiDataSource : IDataSource<string, User>
{
private readonly HttpClient _httpClient;
public ApiDataSource(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<IEnumerable<KeyValuePair<string, User>>> LoadAllAsync(
CancellationToken cancellationToken = default)
{
var users = await _httpClient.GetFromJsonAsync<List<User>>("/api/users", cancellationToken);
return users?.ToDictionary(u => u.Id) ?? new Dictionary<string, User>();
}
}
Register Your Data Source
// Register as scoped service
builder.Services.AddScoped<IDataSource<int, Product>, DataFromDbSource>();
Grouped Cache
ItemsCache supports pre-computed grouped indexes that are automatically maintained in memory. This trades memory for CPU performance, providing O(1) lookups for grouped data.
Register Grouped Cache Services
// First, register the base cache service
builder.Services.AddItemsCache<int, Product>();
// Group by category (string key)
builder.Services.AddItemsCacheGrouped<int, Product, string>(
p => p.Category ?? "Uncategorized");
// Group by active status (bool key)
builder.Services.AddItemsCacheGrouped<int, Product, bool>(
p => p.IsActive);
Use Grouped Cache in Controllers
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IItemsCacheService<int, Product> _productItemsCache;
private readonly IItemsCacheGroupedService<Product, string> _categoryGroupedCache;
private readonly IItemsCacheGroupedService<Product, bool> _activeGroupedCache;
private readonly ILogger<ProductsController> _logger;
public ProductsController(
IItemsCacheService<int, Product> productItemsCache,
IItemsCacheGroupedService<Product, string> categoryGroupedCache,
IItemsCacheGroupedService<Product, bool> activeGroupedCache,
ILogger<ProductsController> logger)
{
_productItemsCache = productItemsCache;
_categoryGroupedCache = categoryGroupedCache;
_activeGroupedCache = activeGroupedCache;
_logger = logger;
}
// Get all products
[HttpGet]
public ActionResult<IEnumerable<Product>> GetAllProducts()
{
var products = _productItemsCache.GetAll().ToDictionary();
return Ok(products.Values);
}
// Get product by ID
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(int id)
{
if (_productItemsCache.TryGetByKey(id, out var product))
{
return Ok(product);
}
return NotFound($"Product with ID {id} not found");
}
// Get products by category
[HttpGet("grouped/category/{category}")]
public ActionResult<IEnumerable<Product>> GetProductsByCategory(string category)
{
var products = _categoryGroupedCache.GetByGroupKey(category).ToList();
return Ok(products);
}
// Get active products
[HttpGet("grouped/active")]
public ActionResult<IEnumerable<Product>> GetProductsGroupedByActive()
{
var products = _activeGroupedCache.GetByGroupKey(true);
return Ok(products);
}
// Get cache statistics
[HttpGet("cache/stats")]
public ActionResult<object> GetCacheStats()
{
var allProducts = _productItemsCache.GetAll().ToDictionary();
var stats = new
{
TotalProducts = allProducts.Count,
ActiveProducts = allProducts.Values.Count(p => p.IsActive),
Categories = allProducts.Values.Select(p => p.Category).Distinct().Count(),
LastRetrieved = DateTime.UtcNow
};
return Ok(stats);
}
}
API Endpoints Example
With the above controller, you have the following endpoints:
GET /api/products- Get all productsGET /api/products/{id}- Get product by IDGET /api/products/grouped/category/{category}- Get products by category (e.g., "Electronics", "Furniture")GET /api/products/grouped/active- Get all active productsGET /api/products/cache/stats- Get cache statistics
Key Features
- Automatic Updates: Grouped indexes are automatically updated when cache items change
- Memory Efficient: Pre-computed indexes eliminate CPU overhead on retrieval
- Multiple Groupings: Register multiple grouped services for different grouping strategies
- Thread Safe: All operations are thread-safe
- Type Safe: Strongly typed group keys (string, bool, int, etc.)
Sample Project
A complete working example is available in the samples/SampleApi directory. This sample demonstrates all features of ItemsCache including:
- Basic cache operations
- Grouped cache by category and active status
- Polling refresh with database change detection
- Prometheus metrics integration
- Entity Framework Core integration
- RESTful API endpoints
Running the Sample
- Navigate to the sample directory:
cd samples/SampleApi
- Restore and build:
dotnet restore
dotnet build
- Run the application:
dotnet run
- Access the API:
- Swagger UI:
https://localhost:5001/swagger(or the port shown in console) - Prometheus Metrics:
https://localhost:5001/metrics
Sample API Endpoints
The sample provides the following endpoints:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/products |
Get all products from cache |
| GET | /api/products/{id} |
Get a specific product by ID |
| GET | /api/products/grouped/category/{category} |
Get products by category |
| GET | /api/products/grouped/active |
Get active products |
| GET | /api/products/cache/stats |
Get cache statistics |
Sample Features Demonstrated
- Database Integration: Uses Entity Framework Core with in-memory database
- Initial Data Load: Products are loaded from database on startup
- Polling Refresh: Cache automatically refreshes every 30 seconds (configurable)
- Change Detection: Only updated/deleted items are refreshed
- Grouped Queries: Fast O(1) lookups by category and active status
- Metrics: Prometheus metrics for monitoring cache performance
Sample Configuration
The sample uses the following configuration in appsettings.json:
{
"CacheOptions": {
"RefreshInterval": "00:00:30"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"ItemsCache": "Information"
}
}
}
Exploring the Sample Code
Key files to examine:
Program.cs- Complete service registration and configurationControllers/ProductsController.cs- API endpoints using cache servicesServices/DataFromDbSource.cs- Initial data loading implementationServices/DataFromDbSourceWithRefresh.cs- Polling refresh implementationServices/PrometheusMetricsRecorder.cs- Custom metrics recorderModels/Product.cs- Product entity modelModels/RefreshContext.cs- Refresh context for polling
Architecture
ItemsCache follows SOLID principles with a clean, modular architecture:
ItemsCache.Core.Abstraction
├── IDataSource<T>
├── IItemsCacheService<T>
└── IItemsCacheServiceWithModifications<T>
ItemsCache.Core
├── ItemsCacheService<T>
├── ItemsCacheLoader<T>
└── CacheInitHostedService
ItemsCache.Refresh.Abstraction
├── IRefreshItemCacheHandler<T>
└── IRefreshItemCacheHandlerFactory<T>
ItemsCache.Refresh.Core
├── RefreshItemCacheHandler<T>
└── RefreshItemCacheHandlerFactory<T>
ItemsCache.Refresh.Polling
├── PollingRefreshService<T>
└── PollingRefreshHostedService<T>
ItemsCache.RetryPolicy.Abstraction
├── IRetryPolicy<T>
└── RetryPolicyOptions<T>
ItemsCache.RetryPolicy.Polly
└── PollyRetryPolicy<T>
Performance Considerations
- Memory Efficient: Uses weak references and proper disposal patterns
- Thread Safe: All operations are thread-safe and optimized for concurrent access
- Lazy Loading: Data is loaded only when needed
- Background Processing: Refresh operations don't block main thread
- Configurable Limits: Set memory and performance limits as needed
Contributing
We welcome contributions! Please see our Contributing Guidelines for details.
Development Setup
- Clone the repository
- Install .NET 9.0 SDK
- Run
dotnet restore - Run
dotnet build - Run
dotnet test
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Changelog
See CHANGELOG.md for a list of changes and version history.
Made with ❤️ by the ItemsCache Contributors
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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 was computed. 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. |
-
net6.0
- ItemsCache.Core.Abstraction (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling.Abstraction (>= 0.0.1-preview.18)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Scrutor (>= 4.2.2)
-
net7.0
- ItemsCache.Core.Abstraction (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling.Abstraction (>= 0.0.1-preview.18)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Scrutor (>= 4.2.2)
-
net8.0
- ItemsCache.Core.Abstraction (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling.Abstraction (>= 0.0.1-preview.18)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Scrutor (>= 4.2.2)
-
net9.0
- ItemsCache.Core.Abstraction (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling (>= 0.0.1-preview.18)
- ItemsCache.Refresh.Polling.Abstraction (>= 0.0.1-preview.18)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Scrutor (>= 4.2.2)
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 |
|---|---|---|
| 0.0.1-preview.18 | 97 | 12/12/2025 |