ICommandor 1.1.0
dotnet add package ICommandor --version 1.1.0
NuGet\Install-Package ICommandor -Version 1.1.0
<PackageReference Include="ICommandor" Version="1.1.0" />
<PackageVersion Include="ICommandor" Version="1.1.0" />
<PackageReference Include="ICommandor" />
paket add ICommandor --version 1.1.0
#r "nuget: ICommandor, 1.1.0"
#:package ICommandor@1.1.0
#addin nuget:?package=ICommandor&version=1.1.0
#tool nuget:?package=ICommandor&version=1.1.0
Commandor
A lightweight CQRS/Mediator library for .NET with automatic caching and source generation.
Installation
dotnet add package ICommandor
Quick Start
1. Define Your Service Interface
using Commandor;
public interface IColorService : ICommandorService
{
[QueryHandler]
Task<List<ColorEntity>> GetAll(GetAllColorsQuery query, CancellationToken ct = default);
[QueryHandler]
Task<ColorEntity?> GetById(GetColorQuery query, CancellationToken ct = default);
[CommandHandler]
Task<ColorEntity> Create(CreateColorCommand command, CancellationToken ct = default);
[CommandHandler]
Task Update(UpdateColorCommand command, CancellationToken ct = default);
}
2. Implement Your Service
public class ColorService : IColorService
{
private readonly AppDbContext _db;
private readonly ICommandor _commandor;
public ColorService(AppDbContext db, ICommandor commandor)
{
_db = db;
_commandor = commandor;
}
public async Task<ColorEntity> Create(CreateColorCommand command, CancellationToken ct = default)
{
var color = new ColorEntity { Name = command.Name };
_db.Colors.Add(color);
await _db.SaveChangesAsync(ct);
// Invalidate cache after mutation
_commandor.Invalidate<IColorService>();
return color;
}
public Task<List<ColorEntity>> GetAll(GetAllColorsQuery query, CancellationToken ct = default)
=> _db.Colors.ToListAsync(ct);
public Task<ColorEntity?> GetById(GetColorQuery query, CancellationToken ct = default)
=> _db.Colors.FindAsync(new object[] { query.Id }, ct).AsTask();
public async Task Update(UpdateColorCommand command, CancellationToken ct = default)
{
var color = await _db.Colors.FindAsync(new object[] { command.Id }, ct);
if (color != null)
{
color.Name = command.Name;
await _db.SaveChangesAsync(ct);
// Invalidate cache after mutation
_commandor.Invalidate<IColorService>();
}
}
}
3. Register Services
var services = new ServiceCollection();
services.AddCommandor();
services.AddCommandorService<IColorService, ColorService>();
4. Use in Controllers
public class ColorsController : ControllerBase
{
private readonly ICommandor _commandor;
public ColorsController(ICommandor commandor) => _commandor = commandor;
[HttpGet]
public Task<List<ColorEntity>> GetAll()
=> _commandor.SendAsync(new GetAllColorsQuery());
[HttpPost]
public Task<ColorEntity> Create(CreateColorCommand command)
=> _commandor.SendAsync(command);
}
Features
Automatic Caching
[QueryHandler]results are automatically cached usingIMemoryCache- Cache is invalidated per service using
ICommandor.Invalidate<TService>() - No manual cache key management needed
Cache Invalidation
New in v1.0.7: Use ICommandor for cache invalidation:
// Invalidate all cached queries for a service
_commandor.Invalidate<ITodoService>();
// Or async version
await _commandor.InvalidateAsync<ITodoService>();
Source Generation
Commandor automatically generates handler classes for methods marked with [CommandHandler] or [QueryHandler]. No boilerplate code needed!
Important Notes
Command/Query Pattern
All method parameters must implement IRequest<TResponse> or IRequest. Primitive types cannot be used directly.
❌ Incorrect:
public interface ITodoService : ICommandorService
{
[CommandHandler]
Task<Todo> CreateTodoAsync(string title); // ❌ string is not IRequest
[QueryHandler]
Task<Todo?> GetTodoByIdAsync(int id); // ❌ int is not IRequest
}
✅ Correct:
// Define request/query records
public record CreateTodoCommand(string Title) : IRequest<Todo>;
public record GetTodoByIdQuery(int Id) : IRequest<Todo?>;
public interface ITodoService : ICommandorService
{
[CommandHandler]
Task<Todo> CreateTodoAsync(CreateTodoCommand command, CancellationToken ct = default);
[QueryHandler]
Task<Todo?> GetTodoByIdAsync(GetTodoByIdQuery query, CancellationToken ct = default);
}
Method Naming Conventions
Recommended naming patterns:
- Commands:
Create...,Update...,Delete...,Process... - Queries:
Get...,Find...,List...,Search...
Cache TTL (Optional)
Specify cache duration per query:
[QueryHandler(CacheTtlSeconds = 300)] // Cache for 5 minutes
Task<List<Product>> GetProducts(GetProductsQuery query, CancellationToken ct = default);
Migration from v1.0.6
If upgrading from v1.0.6 or earlier:
Old:
cache.Remove(cacheKey); // Manual cache key management
New:
_commandor.Invalidate<IYourService>(); // Service-level invalidation
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net8.0
- Microsoft.Extensions.Caching.Memory (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
-
net9.0
- Microsoft.Extensions.Caching.Memory (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
test