An attribute-driven in-memory caching extension for the MitMediator
dotnet add package MitMediator.InMemoryCache -v 9.0.0-alfa-2// Register handlers and IMediator
builder.Services.AddMitMediator();
// Register MemoryCache, InMemoryCacheBehavior,
// scan information about all IRequest<>
builder.Services.AddRequestsInMemoryCache()Warning
Make sure .AddRequestsInMemoryCache() is registered as the last IPipelineBehavior. Cached responses will short-circuit the pipeline and prevent further execution
To customize MemoryCache options and specify assemblies to scan:
builder.Services.AddRequestsInMemoryCache(
new MemoryCacheOptions { SizeLimit = 1000 },
new []{typeof(GetQuery).Assembly});`Decorate your request classes with attribute [CacheResponse]
Requests decorated with the [CacheResponse] attribute will have their responses cached in memory. You can control expiration, entry size, and define which requests should invalidate the cache
| Name | Description |
|---|---|
expirationSeconds |
Absolute expiration time in seconds, relative to the current moment. Set null for indefinitely |
entrySize |
The size of the cache entry item. For collections, size is calculated per element. Default value is 1 |
requestsToClearCache |
Types of requests that will trigger cache invalidation |
Use IMediator extension methods to clear cached responses:
Clear cache for specific request data:
mediator.ClearResponseCacheAsync(request, ct);Clear all cached responses for a request type
mediator.ClearAllResponseCacheAsync<GetBookQuery>(ct);Cache indefinitely:
[CacheResponse]
public struct GetGenresQuery : IRequest<Genre[]>;Default
entrySizeis 1
Cache for 10 seconds:
[CacheResponse(10)]
public struct GetBookQuery : IRequest<Book>
{
public int BookId { get; set; }
}Invalidate cache on specific requests:
[CacheResponse(typeof(DeleteAuthorCommand), typeof(UpdateAuthorCommand))]
public struct GetAuthorsByFilterQuery : IRequest<Author[]>
{
public int? Limit { get; init; }
public int? Offset { get; init; }
public string? FreeText { get; init; }
}Set custom entry size and time (30s)
[CacheResponse(30, 4)]
public struct GetBooksByFilterQuery : IRequest<Book[]>
{
public int? Limit { get; init; }
public int? Offset { get; init; }
public string? FreeText { get; init; }
}For
ICollectiontypes, the cache entry size isresponse.Count * entrySize
Clear cache after updating data:
public async ValueTask<Book> HandleAsync(UpdateBookTitleCommand command, CancellationToken cancellationToken)
{
var book = await _booksRepository.FirstOrDefaultAsync(b => b.BookId == command.BookId, cancellationToken);
book.SetTitle(command.Title);
await _booksRepository.UpdateAsync(book, cancellationToken);
// Clear cached response for the updated book
await _mediator.ClearResponseCacheAsync(new GetBookQuery() { BookId = command.BookId }, cancellationToken);
return book;
}Responses are cached per unique request data. For example,
GetBookQuerycaches a separate response for eachBookId
See samples
MIT