我想将一个存储库包装在另一个存储库中,该存储库将在内部使用传入的存储库来处理缓存。
这样,我的缓存逻辑可以与存储库实现完全分开。这种模式还使我可以轻松地从内存缓存更改为分布式缓存,也就是说,我可以拥有使用不同缓存类型的不同缓存存储库,因此可以根据环境插入它们。在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库之一来执行此操作。对应用装饰器模式提供最佳支持的三个库是AutofacStructureMapSimple Injector

10-08 00:49