This library helps you to cache your services responses with aspect-oriented approach
Let's see how easy to use AybCache
- Install
AybCache
NuGet package from here.
PM> dotnet add package AybCache
- Add
IDistributedCache
to your IoC
Here is simple example of injecting IDistributedCache
as Redis
var redisConnectionString = builder.Configuration.GetValue<string>("Redis:ConnectionString");
builder.Services.AddDistributedRedisCache(options =>
{
options.Configuration = redisConnectionString;
});
builder.Services.AddSingleton<IConnectionMultiplexer>(_ => ConnectionMultiplexer.Connect(redisConnectionString));
- Add services.AddAybCache() in program.cs
builder.Services.AddAybCache();
- Add proxied services with using
AddProxiedScoped()
// Repository example
builder.Services.AddProxiedScoped<IProductRepository, ProductRepository>();
// HttpClient example
builder.Services.AddProxiedScoped<IAgifyHttpClient, AgifyHttpClient>();
// Mediator example
builder.Services.AddProxiedScoped<IRequestHandler<GetNameQuery, string>, GetNameQueryHandler>();
- Add the
[AybCache]
attribute which method you want to cache.
[AybCache(Seconds = 600, CacheKey = CacheKeys.Repository.Products)]
public async Task<List<Product>> GetProducts()
{
Thread.Sleep(5000);
return await Task.Run(() => Task.FromResult(_products.ToList()));
}
[AybCache(Seconds = 600, CacheKey = CacheKeys.Repository.ProductsByBrand)]
public async Task<List<Product>> GetProductsByBrand(string brand)
{
Thread.Sleep(5000);
return await Task.Run(() => Task.FromResult(_products.Where(x => x.Brand == brand).ToList()));
}
You can see the difference and main idea while checking the attached images so you can easily cache your repository, mediator handler or httpclient responses
To further understand the library, please review the Sample API project.
We have cache key generate login in CacheKeyGenerator.GenerateCacheKey()
method.
Example Consider the following example of a defined cache keys:
public static class CacheKeys
{
public static class Repository
{
public const string Products = "repository:products";
public const string ProductsByBrand = "repository:products:{0}";
}
public static class Mediator
{
public const string Name = "mediator:name:{0}";
}
}
These are the techniques we wish to cache.
// repository:products:{0}
// repository:products:{{brand}} used as cache key
[AybCache(Seconds = 600, CacheKey = CacheKeys.Repository.ProductsByBrand)]
public async Task<List<Product>> GetProductsByBrand(string **brand**)
{
Thread.Sleep(5000);
return await Task.Run(() => Task.FromResult(_products.Where(x => x.Brand == brand).ToList()));
}
Or for strongly typed params
// mediator:name:{0}
// mediator:name:{{GetNameQuery.CacheKey}} used as cache key
// ICacheKeyHolder give us the cache key prop that we used this field for generating the cache key
[AybCache(Seconds = 6000, CacheKey = CacheKeys.Mediator.Name)]
public async Task<string> Handle(GetNameQuery request, CancellationToken cancellationToken)
{
return await Task.Run(() => Task.FromResult(request.Name), cancellationToken);
}
public class GetNameQuery : IRequest<string>, ICacheKeyHolder
{
public string Name { get; set; }
public string CacheKey => Name;
}