1 Services.Users.Caching.RoleCacheEventConsumer
using Core.Caching;
using Core.Domain.Users;
using Services.Caching;
namespace Services.Users.Caching
{
/// <summary>
/// 摘要:
/// 通过该类中的方法成员,在角色实体的1个实例执行插入、更新或持久化/逻辑删除操作后,为该实体实例的分布式缓存的强制移除操作提供数据支撑,从而为新变更的实例缓存操作,预留出相应的内存空间。
/// </summary>
public class RoleCacheEventConsumer : CacheEventConsumer<Role>
{
/// <param name="entity">角色实体的1个指定实例。</param>
/// <summary>
/// 【异步清理缓存】
/// <remarks>
/// 摘要:
/// 执行插入、更新或删除操作时,从分布式数据库中强制移除1个指定的缓存项(键/(“JSON”编码格式的)值对)和字典实例中强制移除1个指定的键/值对。
/// </remarks>
/// </summary>
protected override async Task ClearCacheAsync(Role entity)
{
await RemoveByPrefixAsync(EntityCacheDefaults<Role>.AllCacheKey.Key);
}
}
}
2 重构Framework.Infrastructure.DependencyInjectionStartup. ConfigureServices
services.AddSingleton<IEventPublisher, EventPublisher>();
var typeFinder = Singleton<ITypeFinder>.Instance;
//通过反射方式把继承于“IConsumer<>”接口的所有具体实现类进行实例化后,把这些实例注入到.Net(Core)内置容器中。
var consumers = typeFinder.FindClassesOfType(typeof(IConsumer<>)).ToList();
foreach (var consumer in consumers)
foreach (var findInterface in consumer.FindInterfaces((type, criteria) =>
{
var isMatch = type.IsGenericType && ((Type)criteria!).IsAssignableFrom(type.GetGenericTypeDefinition());
return isMatch;
}, typeof(IConsumer<>)))
services.AddScoped(findInterface, consumer);
3 WebApi.Controllers.EventPublisherTestController
using Core.Caching;
using Core.Domain.Users;
using Core.Events;
using Data;
using LinqToDB;
using Microsoft.AspNetCore.Mvc;
using WebApi.Models;
namespace WebApi.Controllers
{
[Route("[controller]/[action]")]
[ApiController]
public class EventPublisherTestController : ControllerBase
{
#region 拷贝构造方法与变量
private readonly EFCoreContext _context;
private readonly IStaticCacheManager _staticCacheManager;
private readonly IEventPublisher _eventPublisher;
public EventPublisherTestController(EFCoreContext context,
IStaticCacheManager staticCacheManager,
IEventPublisher eventPublisher)
{
_context = context;
_staticCacheManager = staticCacheManager;
_eventPublisher = eventPublisher;
}
#endregion
[HttpGet]
public async Task<MessageModel<bool>> EventPublisherTestAsync()
{
MessageModel<bool> _messageModel = new MessageModel<bool>();
try
{
List<Role> _roleList = await _context.GetDbSet<Role>().ToListAsync();
_staticCacheManager.PrepareKeyForDefaultCache(EntityCacheDefaults<Role>.AllCacheKey);
await _staticCacheManager.SetAsync(_staticCacheManager.PrepareKeyForDefaultCache(EntityCacheDefaults<Role>.AllCacheKey), _roleList);
Role _role = new Role() { Name = "EventPublisherTest", IsActive = true, Remark = "强制删除触发器的触发调试" };
await _context.GetDbSet<Role>().AddAsync(_role);
_context.SaveChanges();
await _eventPublisher.EntityInsertedAsync(_role);
_messageModel.Success = true;
_messageModel.Message = "已经成功触发强制删除触发器!";
return _messageModel;
}
catch (Exception exception)
{
_messageModel.Status = 500;
_messageModel.Success = false;
_messageModel.Message = "触发强制删除触发器失败:"+ exception.Message;
return _messageModel;
}
}
}
}
4 对于分布式缓存强制移除泛型注销器定义的一些思考
1、到目前为止.Net(Core)7的内置依赖注入容器依然不能自动的把多泛型继承类进行实例化,这是“CacheEventConsumer<TEntity>”类被定义为抽象类的原因,也是继承于“IConsumer<>”接口的所有具体实现类必须通过反射方式进行实例化的原因。
2、本人认为对“CacheEventConsumer<TEntity>”类进行继承,从而实现多泛型继承类的实例化,并不是一种最好的解决方案,例如:“RoleCacheEventConsumer”,这样会增加程序定义实现的复杂性。
3、本人认为更好解决方案之一是:
3.1、直接把“CacheEventConsumer<TEntity>”类被定义为单泛型继承类。
3.2、直接把“CacheEventConsumer<TEntity>”类被定义为具体实现(非抽象)类。
3.3、删除例如:“RoleCacheEventConsumer”这样的继承类。
3.4、直接通过“CacheEventConsumer<TEntity>”类,实现分布式缓存强制移除操作,而非“RoleCacheEventConsumer”,这样的继承类。
4、本人认为更好解决方案之二是:
4.1、通过第3方依赖注入容器:“Autofac.Extensions.DependencyInjection”,据说该依赖注入容器能够自动的把多泛型继承类进行实例化。
4.2、直接把“CacheEventConsumer<TEntity>”类被定义为具体实现(非抽象)类。
4.3、删除例如:“RoleCacheEventConsumer”这样的继承类。
4.4、直接通过“CacheEventConsumer<TEntity>”类,实现分布式缓存强制移除操作,而非“RoleCacheEventConsumer”,这样的继承类。
以上两种方案都是一种解决思路,没有经过测试,如果有时间,本人会重点以第一种思路方案对分布式缓存强制移除泛型注销器定义实现进行重构
对以上功能更为具体实现和注释见:230203_024shopDemo(分布式缓存强制删除触发器的触发调试)。