首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现Scrutor,但只在几个方法上扩展缓存

实现Scrutor,但只在几个方法上扩展缓存
EN

Stack Overflow用户
提问于 2020-08-26 00:13:01
回答 1查看 98关注 0票数 1

我计划实现Scrutor

代码语言:javascript
复制
public interface ICustomersRepository
{
   Task<CustomerDto> GetCustomerAsync(Guid customerId);
   Task<bool> SaveCustomer(CustomerDto customer);
}

public class CustomersRepository : ICustomersRepository
{
   private readonly List<CustomerDto> _customers = new List<CustomerDto>
   {
      new CustomerDto{Id = Guid.Parse("64fa643f-2d35-46e7-b3f8-31fa673d719b"), Name = "Nick Chapsas"},
      new CustomerDto{Id = Guid.Parse("fc7cdfc4-f407-4955-acbe-98c666ee51a2"), Name = "John Doe"},
      new CustomerDto{Id = Guid.Parse("a46ac8f4-2ecd-43bf-a9e6-e557b9af1d6e"), Name = "Sam McRandom"}
   };
        
   public Task<CustomerDto> GetCustomerAsync(Guid customerId)
   {
      return Task.FromResult(_customers.SingleOrDefault(x => x.Id == customerId));
   }

   public Task<bool> SaveCustomer(CustomerDto customer)
   {
       return "Save Customer here and return bool";
   }
}

实现缓存存储库:

代码语言:javascript
复制
public class CachedCustomersRepository : ICustomersRepository
    {
        private readonly ICustomersRepository _customersRepository; //CustomersRepository
        private readonly ConcurrentDictionary<Guid, CustomerDto> _cache = new ConcurrentDictionary<Guid, CustomerDto>();
        
        public CachedCustomersRepository(ICustomersRepository customersRepository)
        {
            _customersRepository = customersRepository;
        }
        
        public async Task<CustomerDto> GetCustomerAsync(Guid customerId)
        {
            if (_cache.ContainsKey(customerId))
            {
                return _cache[customerId];
            }

            var customer = await _customersRepository.GetCustomerAsync(customerId);
            _cache.TryAdd(customerId, customer);
            return customer;
        }
    }

下面是我做DI的方法:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
   services.AddControllers();

   services.AddSingleton<ICustomersRepository, CustomersRepository>();
   services.Decorate<ICustomersRepository, CachedCustomersRepository>();
}

我看到的问题是ICustomerRepository同时具有GetCustomerAsync和SaveCustomer方法,我可以在CacheCustomerRepository中实现ICustomerRepository并定义GetCustomerAsync方法,但我怎么能忽略SaveCustomer,因为它不能作为CacheCustomerRepository类中的缓存方法。如果我没有在CacheCustomerRepository中定义方法,我会得到错误,因为缺少接口实现,如何以干净的方式实现scrutor,有没有一种方法只实现几个需要缓存的方法,而rest可以在主库类中?

我可以考虑只在保存方法的CacheCustomersRepository中包含骨架,但这是一种干净的方法吗?而且,如果我的CustomerRepository有50个方法,其中只有5个方法需要缓存实现,那么这是非常多余的,并且不是将所有骨架方法都放到缓存存储库中的好方法。

我们怎样才能以一种干净的方式实现Scrutor呢?有什么建议吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-26 08:15:21

为了解决您的特定问题,不需要处理缓存的方法,只需将其委托给修饰对象即可。

代码语言:javascript
复制
public class CachedCustomersRepository : ICustomersRepository
{
    private readonly ICustomersRepository _customersRepository; //CustomersRepository
    private readonly ConcurrentDictionary<Guid, CustomerDto> _cache = new ConcurrentDictionary<Guid, CustomerDto>();
        
    public CachedCustomersRepository(ICustomersRepository customersRepository)
    {
        _customersRepository = customersRepository;
    }
        
    public async Task<CustomerDto> GetCustomerAsync(Guid customerId)
    {
        if (_cache.ContainsKey(customerId))
        {
            return _cache[customerId];
        }

        var customer = await _customersRepository.GetCustomerAsync(customerId);
        _cache.TryAdd(customerId, customer);
        return customer;
    }

    // No need to cache anything, just delegate it, although you might need to
    // invalidate the cache if a cached customer is saved
    public Task<bool> SaveCustomer(CustomerDto customer) => 
        _customersRepository.SaveCustomer(customer);
}

至于更广泛的问题,即如果您的存储库有50个方法,而对项目的其余部分一无所知,那么如何处理这个问题,我的第一反应是,现有的设计可能有一些改进的空间。这种假设的情况很可能是实践interface seggregation principle的好机会。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63582992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档