.net 具有通用存储库的装饰器设计模式

du7egjpx  于 2022-11-19  发布在  .NET
关注(0)|答案(2)|浏览(133)

我一直在研究装饰器设计模式(我对设计模式这一主题是新的)。
我已经在使用BaseRepository模式。但是我还想使用一些缓存。
下面的示例只是一个转储示例。
所以我有了IGenericRepository接口和它的实现。

public interface IGenericRepository<T> where T : class
{
    T GetById(int id);
    IEnumerable<T> GetAll();
    Task<T> GetByIdAsync(int id);

    T Add(T entity);
    void AddRange(IEnumerable<T> entities);
    Task<T> AddAsync(T entity);
    Task AddRangeAsync(IEnumerable<T> entities);

    void Remove(T entity);
    void RemoveRange(IEnumerable<T> entities);

    int SaveChanges();
    Task<int> SaveChangesAsync();
}

然后,我创建了一个自定义存储库,例如IBlogRepository

public interface IBlogRepository : IBaseRepository<Blog>
{
    public Task<Blog> GetBlogsByCreatorAsync(int creatorId);
}

通过实施BlogRepository

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
    public BlogRepository(DbContext db) : base(db)
    {
    }

    public Task<Blog> GetBlogsByCreatorAsync(int creatorId) =>
        db.Blogs.Where(b => b.CreatorId == creatorId)
                .ToListAsync();
}

我觉得这很酷,然后我意识到我需要提高我的“速度”。我开始使用IMemoryCache,但在仓库代码如下。

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
    public BlogRepository(DbContext db, IMemoryCache cache) : base(db)
    {
    }

    public Task<Blog> GetBlogsByCreatorAsync(int creatorId) 
    {
        // if in cache else go to db
    } 
    
}

然后我遇到了装饰模式,我想为什么不呢,我开始使用它,但我现在很挣扎。我创建了CachedBlogRepository,它是实现IBlogRepository,但当我要求VS实现所有接口方法时...

public class CachedBlogRepository : IBlogRepository
{
   //All BaseRepository methods appeared here...
   //But I want cache only the GetBlogsByCreatorAsync method
}

那么,这里的最佳实践是什么?我遗漏了什么还是我做错了什么?

nkoocmlb

nkoocmlb1#

首先我不明白这一部分:
博客存储库:基本库、IBlog库
难道不应该是:
博客存储库:IBlog存储库?
现在,当涉及到装饰器模式时,我会这样做:

public interface IGenericRepository<T> where T : class
    {
        T GetById(int id);
        IEnumerable<T> GetAll();
        Task<T> GetByIdAsync(int id);
    
        T Add(T entity);
        void AddRange(IEnumerable<T> entities);
        Task<T> AddAsync(T entity);
        Task AddRangeAsync(IEnumerable<T> entities);
    
        void Remove(T entity);
        void RemoveRange(IEnumerable<T> entities);
    
        int SaveChanges();
        Task<int> SaveChangesAsync()
 }

(组件)

public class BlogRepository : BaseRepository<Blog>, IBlogRepository
{
    public BlogRepository(DbContext db) : base(db)
    {
    }

    public Task<Blog> GetBlogsByCreatorAsync(int creatorId) =>
        db.Blogs.Where(b => b.CreatorId == creatorId)
                .ToListAsync();
}

(混凝土构件)

abstract class Decorator :  IGenericRepository<T>
{
    protected IGenerecRepository _repository;

    public Decorator( IGenerecRepository repository)
    {
        this._repository = repository;
    }

    public override Task<Blog> GetBlogsByCreatorAsync()
    {
        if (this._repository != null)
        {
            return this._repository.GetBlogsByCreatorAsync();
        }
        else
        {
            return string.Empty;
        }
    }
}

(Base装饰器)

class CacheDecorator : Decorator
    {
        public CacheDecorator(IGenericRepository repo) : base(repo)
        {
        }
        public override Task<Blog> GetBlogsByCreatorAsync()
        {
            //cache behavior
        }
    }

用途:

BlogRepository _basicRepo = new BlogRepository();

CacheDecorator _cacheDecorator = new CacheDecorator(_basicRepo);

_cacheDecorator.GetBlogsByCreatorAsync(creatorId);

装饰器模式将行为添加到主要的基本行为中。它需要一个 Package 对象(基本组件)来 Package 新的行为。

qnzebej0

qnzebej02#

它看起来像是一个可以使用CachedRepository pattern的地方。
我强烈推荐您阅读这篇关于Building a CachedRepository in ASPNET Core的美丽文章
所以应用CachedRepository模式后会看起来像这样:

public List<Blog> GetBlogsByCreatorAsync(int id)
{
    string key = MyModelCacheKey + "-" + id;

    return _cache.GetOrCreate(key, entry =>
    {
        entry.SetOptions(cacheOptions);
        return _repository.GetBlogsByCreatorAsync(id);
    });
}

您可以看到source code at gihub

相关问题