我想将一个存储库包装在另一个存储库中,该存储库将在内部使用传入的存储库来处理缓存。
这样,我的缓存逻辑可以与存储库实现完全分开。这种模式还使我可以轻松地从内存缓存更改为分布式缓存,也就是说,我可以拥有使用不同缓存类型的不同缓存存储库,因此可以根据环境插入它们。在Azure上,我可以使用分布式缓存,但是在单个服务器上,例如,我可以使用内存缓存。
public sealed class CachingFooRepository : IFooRepository
{
private IFooRepository repo;
private IMemoryCache cache;
public CachingFooRepository(IFooRepository implementation, IMemoryCache cache, IFooCachingRules)
{
if ((implementation == null)||(implementation is CachingFooRepository))
{
throw new ArgumentException("you must pass in an implementation of IFooRpository");
}
repo = implementation;
this.cache = cache;
}
public async Task<bool> Save(IFooItem foo)
{
// TODO throw if foo is null
bool result = await repo.Save(user);
string key = "Key-" + foo.Id.ToString();
cache.Remove(key);
return result;
}
public async Task<IFooItem> Fetch(int fooId)
{
string key = "Key-" + fooId.ToString();
object result = cache.Get(key);
if(result != null) { return (foo)result; }
foo = await repo.Fetch(fooId);
if(foo != null)
cache.Set(key, foo);
return foo;
}
}
显然,在CachingFooRepository实现IFooRepository的同时,我必须确保将IFooRepository的不同实现传递到CachingFooRepository的构造函数中,因为它不是IFooRepository的实际实现,而是依赖于实际的实现。
此示例是简化的伪ish代码,可以将缓存以及缓存多长时间作为IFooCachingRules或IOptions或类似内容传入。
所以我的问题是我该如何重新注册服务,以便依赖IFooRepository的事物将获得CachingFooRepository的实例,但是CachingFooRepository将获得IFooRepository的其他实现(例如SqlFooRepository)?
我想保留其他类仅取决于IFooRepository,我不想让任何事情专门取决于CachingFooRepository。
这可能,可行,好主意还是坏主意?
最佳答案
我想将一个存储库包装在另一个存储库中
在内部使用传入的存储库处理缓存。
有一个您正在使用的模式的名称。它称为:Decorator pattern。
一个好主意,一个坏主意?
使用装饰器模式是一个绝妙的主意,因为它使您可以进行添加功能,而不必更改系统的任何现有部分。换句话说,您可以遵守Open/closed principle。
这可能吗
不,ASP.NET Core的内置DI容器带有no easy way do this。您应该使用.NET现有的成熟DI库之一来执行此操作。对应用装饰器模式提供最佳支持的三个库是Autofac,StructureMap和Simple Injector。