实现 Scrutor 但仅在少数方法上扩展缓存
Implementing Scrutor but extend cache on only few methods
我打算实施 Scrutor
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";
}
}
实施缓存存储库:
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:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<ICustomersRepository, CustomersRepository>();
services.Decorate<ICustomersRepository, CachedCustomersRepository>();
}
我看到的问题是 ICustomerRepository 有 GetCustomerAsync 和 SaveCustomer 方法,我可以在 CacheCustomerRepository 中实现 ICustomerRepository 并定义 GetCustomerAsync 方法,但是我怎么能忽略 SaveCustomer,因为它不能作为 CacheCustomerRepository class 中的缓存方法。如果我不在 CacheCustomerRepository 中定义该方法,我将收到错误,因为缺少接口的实现,如何以干净的方式实现 scrutor,有没有一种方法只实现需要缓存的少数方法,其余的可以在主要存储库 class ?
我可以想到只在 CacheCustomersRepository 中包含用于保存方法的骨架,但这是一种干净的方法吗,而且如果我的 CustomerRepository 有 50 个方法,其中只有 5 个方法需要缓存实现,那么它是非常多余的,而不是将所有骨架方法放入缓存存储库的好方法。
我们如何以干净的方式实施 Scrutor?有什么建议吗?
针对你的具体问题,不需要处理缓存的方法,直接委托给装饰对象即可,即
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.
的好机会
我打算实施 Scrutor
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";
}
}
实施缓存存储库:
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:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<ICustomersRepository, CustomersRepository>();
services.Decorate<ICustomersRepository, CachedCustomersRepository>();
}
我看到的问题是 ICustomerRepository 有 GetCustomerAsync 和 SaveCustomer 方法,我可以在 CacheCustomerRepository 中实现 ICustomerRepository 并定义 GetCustomerAsync 方法,但是我怎么能忽略 SaveCustomer,因为它不能作为 CacheCustomerRepository class 中的缓存方法。如果我不在 CacheCustomerRepository 中定义该方法,我将收到错误,因为缺少接口的实现,如何以干净的方式实现 scrutor,有没有一种方法只实现需要缓存的少数方法,其余的可以在主要存储库 class ?
我可以想到只在 CacheCustomersRepository 中包含用于保存方法的骨架,但这是一种干净的方法吗,而且如果我的 CustomerRepository 有 50 个方法,其中只有 5 个方法需要缓存实现,那么它是非常多余的,而不是将所有骨架方法放入缓存存储库的好方法。
我们如何以干净的方式实施 Scrutor?有什么建议吗?
针对你的具体问题,不需要处理缓存的方法,直接委托给装饰对象即可,即
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.
的好机会