Skip to content

Commit 81cf13f

Browse files
modified CHANGELOG and README and uptate version
1 parent c5a57d4 commit 81cf13f

3 files changed

Lines changed: 43 additions & 20 deletions

File tree

AspNetCoreCacheKit/AspNetCoreCacheKit.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
<IsPackable>true</IsPackable>
99
<PackageId>AspNetCoreCacheKit</PackageId>
10-
<Version>2.1.0</Version>
10+
<Version>3.0.0</Version>
1111
<Authors>Simone Marano</Authors>
1212
<Description>Lightweight caching toolkit for ASP.NET Core with group-based keys, per-entry and per-group duration, configurable via appsettings.json and DI-ready design.</Description>
1313
<PackageLicenseExpression>MIT</PackageLicenseExpression>

CHANGELOG.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
---
1313

14-
## [2.1.0] - 2026-03-24
15-
14+
## [3.0.0] - 2026-03-XX
15+
16+
### Added
17+
- Unit test suite (`AspNetCoreCacheKit.Tests`) using xUnit 2.x and real `IMemoryCache`
18+
- Repository restructured to support multiple projects: main project moved to `AspNetCoreCacheKit/` subfolder, tests in `AspNetCoreCacheKit.Tests/`
19+
20+
### Changed
21+
- `ICacheService.Set` is now generic: `void Set<T>(string groupKey, string key, T value, TimeSpan? duration = null)`**breaking change**
22+
- `ICacheService.Set` overload without group is now generic: `void Set<T>(string key, T value, TimeSpan? duration = null)`**breaking change**
23+
24+
### Fixed
25+
- `Set` followed by `GetOrCreate<T>` / `GetOrCreateAsync<T>` now works correctly — previously `Set(object)` was type-incompatible with generic read methods causing cache misses
26+
27+
### Breaking changes
28+
- `Set(string groupKey, string key, object value)``Set<T>(string groupKey, string key, T value)`: update all call sites to use the generic overload
29+
```csharp
30+
// before
31+
_cache.Set("users", "1", user);
32+
33+
// after — type is usually inferred automatically
34+
_cache.Set("users", "1", user);
35+
```
36+
1637
---
1738

1839
## [2.0.0] - 2026-03-24
@@ -66,7 +87,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6687
- MIT license
6788

6889
---
69-
[Unreleased]: https://github.com/simoneM93/AspNetCoreCacheKit/compare/v2.1.0...HEAD
70-
[2.1.0]: https://github.com/simoneM93/AspNetCoreCacheKit/compare/v2.0.0...v2.1.0
90+
[Unreleased]: https://github.com/simoneM93/AspNetCoreCacheKit/compare/v3.0.0...HEAD
91+
[3.0.0]: https://github.com/simoneM93/AspNetCoreCacheKit/compare/v2.0.0...v3.0.0
7192
[2.0.0]: https://github.com/simoneM93/AspNetCoreCacheKit/compare/v1.0.0...v2.0.0
7293
[1.0.0]: https://github.com/simoneM93/AspNetCoreCacheKit/releases/tag/v1.0.0

README.md

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
# AspNetCoreCacheKit
22

33
[![NuGet](https://img.shields.io/nuget/v/AspNetCoreCacheKit.svg)](https://www.nuget.org/packages/AspNetCoreCacheKit)
4-
[![Publish to NuGet](https://github.com/simoneM93/AspNetCoreCacheKit/actions/workflows/publish.yml/badge.svg)](https://github.com/simoneM93/AspNetCoreCacheKit/actions/workflows/publish.yml)
54
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
65
[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?logo=github-sponsors)](https://github.com/sponsors/simoneM93)
76
[![Changelog](https://img.shields.io/badge/Changelog-view-blue)](CHANGELOG.md)
87

9-
A lightweight caching library for ASP.NET Core featuring **group-based keys**, configurable expiration, and a DI-ready design that wraps `IMemoryCache` in a clean, testable abstraction.
8+
A lightweight caching library for ASP.NET Core featuring **group-based keys**, per-entry and per-group duration, configurable via `appsettings.json`, and a DI-ready design that wraps `IMemoryCache` in a clean, testable abstraction.
109

1110
> **Why AspNetCoreCacheKit?**
1211
> `IMemoryCache` is powerful but low-level. AspNetCoreCacheKit adds group-based key management,
13-
> `appsettings.json` configuration, and a consistent API that makes caching easy to use and easy to mock in tests.
12+
> per-group and per-entry expiration, `appsettings.json` configuration, and a consistent
13+
> type-safe API that makes caching easy to use and easy to mock in tests.
1414
1515
---
1616

1717
## ✨ Features
1818

1919
- 🔑 **Group-based keys** — organise cache entries with prefixes like `"users:123"`
2020
-**`GetOrCreate` and `GetOrCreateAsync`** — read-through pattern out of the box
21+
- ⏱️ **Per-group and per-entry duration** — fine-grained expiration control
2122
- 🗑️ **`Delete`** — remove a single entry by key or group + key
2223
-**Configuration validation** with DataAnnotations
23-
- 📐 **Nullable reference types** support
24+
- 📐 **Nullable reference types** and **generic type-safe `Set<T>`** support
2425
- 🎛️ **`appsettings.json`** configuration with sensible defaults
2526
- 🧪 **DI-ready** — register with one line, mock `ICacheService` in tests
2627

@@ -90,12 +91,12 @@ public class UsersController : ControllerBase
9091
[HttpGet("{id}")]
9192
public async Task<IActionResult> GetUser(int id, CancellationToken ct)
9293
{
93-
// With group key — full key will be "users:42"
94+
// Uses GroupDurations["users"] = 30 min from appsettings
9495
var user = await _cache.GetOrCreateAsync(
9596
"users",
9697
id.ToString(),
9798
_ => GetUserFromDb(id),
98-
ct);
99+
ct: ct);
99100

100101
return user is null ? NotFound() : Ok(user);
101102
}
@@ -148,15 +149,15 @@ var config = await _cache.GetOrCreateAsync("app:config", _ => LoadConfigAsync(),
148149
// Uses GroupDurations["countries"] = 1440 min from appsettings
149150
var countries = _cache.GetOrCreate("countries", () => LoadCountries());
150151

151-
// Explicit override — ignores group and global config
152+
// Explicit override
152153
var result = _cache.GetOrCreate("countries", "IT", () => LoadItaly(), TimeSpan.FromHours(2));
153154
```
154155

155156
### `Set` — explicit write
156157

157158
```csharp
158-
_cache.Set("users", "42", user); // group duration or global
159-
_cache.Set("users", "42", user, TimeSpan.FromMinutes(10)); // explicit override
159+
_cache.Set("users", "42", user); // group duration or global
160+
_cache.Set("users", "42", user, TimeSpan.FromMinutes(10)); // explicit override
160161
```
161162

162163
### `Delete` — remove an entry
@@ -173,28 +174,29 @@ _cache.Delete("app:config");
173174
| Option | Type | Default | Description |
174175
|---|---|---|---|
175176
| `IsEnabled` | `bool` | `true` | Enables or disables caching entirely. When `false`, factories are always invoked. |
176-
| `DurationMinutes` | `int` | `60` | Global default cache duration in **minutes**. Used when no per-entry or per-group duration is set. |
177+
| `DurationMinutes` | `int` | `60` | Global default cache duration in **minutes**. |
177178
| `GroupDurations` | `Dictionary<string, int>` | `{}` | Per-group durations in **minutes**. Key = group name, Value = duration in minutes. |
178179

179180
Setting `IsEnabled: false` is useful in development or testing environments where you want to bypass the cache without changing code.
180181

181182
---
182183

183184
## 🧪 Testing
184-
185+
185186
`ICacheService` is a plain interface — mock it directly in unit tests:
186-
187+
187188
```csharp
188189
var cacheMock = new Mock<ICacheService>();
189-
190+
190191
cacheMock
191192
.Setup(c => c.GetOrCreateAsync(
192193
"users", "1",
193194
It.IsAny<Func<ICacheEntry, Task<User>>>(),
195+
It.IsAny<TimeSpan?>(),
194196
It.IsAny<CancellationToken>()))
195197
.ReturnsAsync(new User { Id = 1, Name = "Simone" });
196198
```
197-
199+
198200
---
199201

200202
## ❤️ Support
@@ -207,4 +209,4 @@ If you find AspNetCoreCacheKit useful, consider sponsoring its development.
207209

208210
## 📄 License
209211

210-
MIT — see [LICENSE](LICENSE) for details.
212+
MIT — see [LICENSE](LICENSE) for details.

0 commit comments

Comments
 (0)