我想缓存来自CommandsHandlers的一些响应。
我已经使用IPipelineBehaviour进行了此操作,但是实际上只有5%的请求必须具有缓存,而其他95%的请求必须跳过此管道。有办法吗?
下面是我的代码。
谢谢!
public class PipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>, IProvideCacheKey
{
private readonly IMemoryCache _cache;
public PipelineBehavior(IMemoryCache cache)
{
_cache = cache;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken,
RequestHandlerDelegate<TResponse> next)
{
// Check in cache if we already have what we're looking for
var cacheKey = request.CacheKey;
if (_cache.TryGetValue<TResponse>(cacheKey, out var cachedResponse))
{
return cachedResponse;
}
// If we don't, execute the rest of the pipeline, and add the result to the cache
var response = await next();
_cache.Set(cacheKey, response);
return response;
}
}
public class GetUserByEmailCommand : Command, IRequest<bool>, IProvideCacheKey
{
public string Email { get; set; }
public string CacheKey => $"{GetType().Name}:{Email}";
public override bool IsValid()
{
ValidationResult = new GetUserByEmailCommandValidation<GetUserByEmailCommand>().Validate(this);
return ValidationResult.IsValid;
}
}
public interface IProvideCacheKey
{
string CacheKey { get; }
}
您可以将缓存行为包装在一个检查中,如果请求不可缓存以使管道继续运行,则绕过该检查。就您而言,您可能只需要在Handle方法开始时检查请求是否实现了您的接口:
if (request is IProvideCacheKey)
{
// perform cache behavior, return if cached and terminate the pipeline
}
// else continue the pipeline
这里有两个很好的例子,更详细地介绍:
https://lurumad.github.io/cross-cutting-concerns-in-asp-net-core-with-meaditr
https://anderly.com/2019/12/12/cross-cutting-concerns-with-mediatr-pipeline-behaviors/