ICommandor 1.0.3
See the version list below for details.
dotnet add package ICommandor --version 1.0.3
NuGet\Install-Package ICommandor -Version 1.0.3
<PackageReference Include="ICommandor" Version="1.0.3" />
<PackageVersion Include="ICommandor" Version="1.0.3" />
<PackageReference Include="ICommandor" />
paket add ICommandor --version 1.0.3
#r "nuget: ICommandor, 1.0.3"
#:package ICommandor@1.0.3
#addin nuget:?package=ICommandor&version=1.0.3
#tool nuget:?package=ICommandor&version=1.0.3
Commandor
Commandor - MediatR uchun zamonaviy, yuqori samaradorlikka ega alternative. ActualLab.Fusion va MediatR'dan ilhomlangan, Source Generator va Automatic Caching bilan.
โจ Asosiy Xususiyatlar
- ๐ Zero Boilerplate - Handler'larni yozish shart emas (Source Generator)
- โก Auto Caching - Query'lar avtomatik cache'lanadi (3-5x tezroq)
- ๐ฅ Fusion Pattern - Dependency tracking va transitive invalidation
- ๐พ GC-free Cache - LiteAPI.Cache (Rust-backed, ultra-fast)
- ๐ฏ Type-Safe - To'liq compile-time xavfsizlik
- ๐ Command/Query Separation -
[CommandHandler]va[QueryHandler] - ๐งช Production Ready - 29/29 test o'tgan, ishonchli
๐ Quick Start
1. O'rnatish
dotnet add package Commandor
2. Command va Query yaratish
using Commandor;
// Commands (Write operations - cache invalidation)
public record CreateProductCommand(string Name, decimal Price) : IRequest<Product>;
public record UpdatePriceCommand(int Id, decimal Price) : IRequest;
// Queries (Read operations - auto caching)
public record GetProductByIdQuery(int Id) : IRequest<Product?>;
3. Service interface - Attribute bilan
public interface IProductService : ICommandorService
{
[CommandHandler] // โจ Handler avtomatik yaratiladi!
Task<Product> CreateProduct(CreateProductCommand cmd, CancellationToken ct = default);
[CommandHandler] // โจ Cache'ni invalidate qiladi
Task UpdatePrice(UpdatePriceCommand cmd, CancellationToken ct = default);
[QueryHandler] // ๐ฅ Natija avtomatik cache'lanadi!
Task<Product?> GetProductById(GetProductByIdQuery query, CancellationToken ct = default);
}
4. Service implementation - Faqat business logic
public class ProductService : IProductService
{
private readonly List<Product> _products = new();
private readonly IComputedCache _cache;
public ProductService(IComputedCache cache) => _cache = cache;
public Task<Product> CreateProduct(CreateProductCommand cmd, CancellationToken ct)
{
var product = new Product
{
Id = Random.Shared.Next(1000, 9999),
Name = cmd.Name,
Price = cmd.Price
};
_products.Add(product);
return Task.FromResult(product);
}
public Task UpdatePrice(UpdatePriceCommand cmd, CancellationToken ct)
{
var product = _products.First(p => p.Id == cmd.Id);
product.Price = cmd.Price;
// Cache'ni qo'lda invalidate qilish (GetProductById cache key)
var cacheKey = CacheKeyBuilder.Build(
typeof(IProductService),
nameof(GetProductById),
new GetProductByIdQuery(cmd.Id));
_cache.Remove(cacheKey);
return Task.CompletedTask;
}
public Task<Product?> GetProductById(GetProductByIdQuery query, CancellationToken ct)
{
// Bu metod avtomatik cache'lanadi! โก
var product = _products.FirstOrDefault(p => p.Id == query.Id);
return Task.FromResult(product);
}
}
5. DI Setup
var services = new ServiceCollection();
// Commandor qo'shish
services.AddCommandor();
// Service va auto-generated handler'larni ro'yxatga olish
services.AddCommandorService<IProductService, ProductService>();
var serviceProvider = services.BuildServiceProvider();
6. Ishlatish
var commandor = serviceProvider.GetRequiredService<ICommandor>();
// 1. Mahsulot yaratish
var product = await commandor.SendAsync(
new CreateProductCommand("iPhone 15 Pro", 15000000));
// 2. Birinchi query - DB'dan (~1.5ms)
var p1 = await commandor.SendAsync(new GetProductByIdQuery(product.Id));
// 3. Ikkinchi query - CACHE'dan (~0.3ms) โกโกโก 5x TEZROQ!
var p2 = await commandor.SendAsync(new GetProductByIdQuery(product.Id));
// 4. Narxni yangilash - cache invalidate
await commandor.SendAsync(new UpdatePriceCommand(product.Id, 14500000));
// 5. Keyingi query - yangi ma'lumot DB'dan
var p3 = await commandor.SendAsync(new GetProductByIdQuery(product.Id));
๐ Performance
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Birinchi Query (DB): ~1.5-2.0ms โ
โ Cached Query: ~0.3-0.6ms โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ Tezlashish: 3-5x โ
โ GC Pressure: ZERO โ
โ Memory: Ultra-efficient โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ Command vs Query
Commands - Write Operations
[CommandHandler] // โ Cache'lanmaydi
Task<Product> CreateProduct(CreateProductCommand cmd);
[CommandHandler] // โก Cache'ni invalidate qiladi
Task UpdatePrice(UpdatePriceCommand cmd);
Xususiyatlari:
- Ma'lumotlarni o'zgartiradi (Create, Update, Delete)
- Cache'lanmaydi
- Tegishli Query'larni invalidate qiladi
Queries - Read Operations
[QueryHandler] // โ
Avtomatik cache'lanadi
Task<Product?> GetProductById(GetProductByIdQuery query);
[QueryHandler] // โ
Avtomatik cache'lanadi
Task<List<Product>> GetAllProducts(GetAllProductsQuery query);
Xususiyatlari:
- Faqat ma'lumot o'qiydi (Read-only)
- Avtomatik cache'lanadi
- Dependency tracking bilan
- Transitive invalidation
๐ฅ Fusion Pattern - Dependency Tracking
Commandor ActualLab.Fusion'dan ilhomlangan dependency tracking mexanizmini ishlatadi:
// A โ B bog'liqligi
var productList = await commandor.SendAsync(new GetProductListQuery());
// Ichida GetProductById chaqirilgan
// GetProductById invalidate bo'lsa
await commandor.SendAsync(new UpdatePriceCommand(1, 15000));
// GetProductList ham invalidate bo'ladi! (Transitive)
var updatedList = await commandor.SendAsync(new GetProductListQuery());
Computed Values
Har bir cached natija Computed<T> sifatida saqlanadi:
public interface IComputed<T>
{
T Value { get; } // Cache'langan qiymat
long Version { get; } // Versiya (invalidation tracking)
ConsistencyState State { get; } // Consistent, Computing, Invalidated
bool IsConsistent(); // Cache hali fresh?
void Invalidate(); // Cache'ni bekor qilish
Task WhenInvalidated(); // Invalidation kutish
}
๐พ LiteAPI.Cache - GC-free Caching
Commandor LiteAPI.Cache 1.1.0 dan foydalanadi:
Afzalliklar
- โก Ultra-fast - Rust-backed native implementation
- ๐ง GC-free - .NET garbage collector'ga ta'sir qilmaydi
- ๐ Thread-safe - Concurrent access safe
- ๐พ Cross-platform - Windows, Linux, macOS
- ๐ Production-ready - Battle-tested
Cache Key Format
ServiceType.MethodName(arg1, arg2, ...)
Misollar:
- ProductService.GetProductById(1)
- ProductService.GetAllProducts()
- UserService.GetUserByEmail("john@example.com")
๐ง Query Caching
[QueryHandler]bilan belgilangan har bir metod uchun generator avtomatikIRequestHandler<TRequest, TResponse>yaratadi va natijaniIComputedCachega yozadi.- Cache key
CacheKeyBuilder.Build(typeof(Service), MethodName, request)formulasi asosida hisoblanadi;requestJSON'ga serializatsiya qilinadi, shuning uchun record/immutable turlar eng qulay variant. services.AddCommandor()chaqirilganda LiteAPI.Cache ishlatiladi; agar native kutubxona topilmasa, avtomatikCommandorMemoryCachega fallback qiladi. XohlasangizIComputedCacheni o'zingiz override qilishingiz mumkin.- TTL (
CacheTtlSeconds) property hozircha rezerv qilingan bo'lib, invalidate jarayoni qo'lda bajariladi. Service implementatsiyasigaIComputedCacheni inject qiling va tegishli key niRemoveqiling (yuqoridagi misolda ko'rsatilganidek). - Cache faqat bir xil request obyekti uchun ishlaydi; request parametrlarini o'zgartirish boshqa cache key beradi va handler qayta bajariladi.
๐ง Qo'shimcha Ma'lumotlar
Commandorpaketini loyihangizga qo'shgandan so'ng, Visual Studio yokidotnet buildyordamida loyihani qayta qurishingiz kerak. Bu, generatorning source code'mizga yaratilishini ta'minlaydi.- IntelliSense va kodni to'ldirish funktsiyalari uchun Visual Studio'da yechimingizni yangilang.
โ FAQ
Methodlarni virtual qilish shartmi?
Yoสปq. Commandor generatori interface deklaratsiyasini oสปqiydi va [CommandHandler]/[QueryHandler] atributlari tushirilgan metodlar asosida ichki handlerlarni yaratadi. Implementatsiya sinfida metodlarni virtual qilish talab qilinmaydi; oddiy Task/Task<T> signaturasi va CancellationToken parametri yetarli.
Query caching nima uchun ishlamayapti?
Commandorpaketini o'rnatganingizga ishonch hosil qiling.- DI'da albatta
services.AddCommandor()va tegishliservices.AddCommandorService<...>()chaqiring โ shu paytda mediator vaIComputedCacheregistratsiya qilinadi. - Request/response turlari
System.Text.Jsontomonidan serializatsiya qilina olishi kerak, chunki cache key va natija JSON orqali saqlanadi. - Default LiteAPI.Cache native kutubxonasini topa olmasa, fallback sifatida
CommandorMemoryCacheishlaydi. Zarurat bo'lsa, o'zingizningIComputedCacheimplementatsiyangizni registratsiya qiling yoki diagnostika uchun log qo'shing. - Cache ni qo'lda invalidate qilish uchun service'ga
IComputedCacheinject qiling vaCacheKeyBuilderorqali kerakli key'ni topib,Removeqiling.
| 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
- LiteAPI.Cache (>= 1.1.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
-
net9.0
- LiteAPI.Cache (>= 1.1.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.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