翼度科技»论坛 编程开发 .net 查看内容

.net8 AOP 实现简单的Json Redis 缓存/业务分离

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
 场景: 在不动 业务逻辑的情况下, 实现读写缓存
   这里使用的AOP的方式 在 方法上加注解, 这目前有个弊端不能传数组, 涉及到排序问题
  1.   /// <summary>
  2.   /// Json Redis缓存
  3.   /// </summary>
  4.   public class RedisInterceptorAttribute : AbstractInterceptorAttribute
  5.   {
  6.       readonly string _cacheKey;
  7.       bool _isDb = false; //是否走缓存
  8.       int _expireSeconds = -1;
  9.    
  10.       public RedisInterceptorAttribute(string cacheKey, int expireSeconds = -1,bool isDb=false)
  11.       {
  12.           _cacheKey = cacheKey;
  13.           _isDb = isDb;
  14.           _expireSeconds = expireSeconds;
  15.       }
  16.       public override async Task Invoke(AspectContext context, AspectDelegate next)
  17.       {
  18.          
  19.           Type returnType = context.ServiceMethod.ReturnType;
  20.           Type genericArgument = returnType.GetGenericArguments()[0];
  21.           // 生成缓存的key
  22.           string cacheKeyWithParams = GenerateCacheKey(context);
  23.           if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
  24.           {
  25.               //通过类型获取缓存方法,并且调用 GetAsync 方法
  26.               MethodInfo method = this.GetType().GetMethod("GetAsync", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  27.               MethodInfo genericMethod = method.MakeGenericMethod(genericArgument);
  28.               var cacheTask = (Task)genericMethod.Invoke(this, new object[] { cacheKeyWithParams });
  29.               await cacheTask.ConfigureAwait(true);
  30.               var resultProperty = cacheTask.GetType().GetProperty("Result");
  31.               var cacheResult = resultProperty.GetValue(cacheTask);
  32.               if (cacheResult != null)
  33.               {
  34.                   context.ReturnValue = ConvertToReturnType(cacheResult, returnType);
  35.                   // 设置缓存的逻辑
  36.                   await Task.CompletedTask;
  37.               }
  38.               else
  39.               {
  40.                   await context.Invoke(next);
  41.                   // 设置缓存
  42.                    if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
  43.                   {
  44.                       MethodInfo setMethod = this.GetType().GetMethod("SetAsync", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  45.                       MethodInfo genericSetMethod = setMethod.MakeGenericMethod(genericArgument);
  46.                       var resultProperty1 = context.ReturnValue.GetType().GetProperty("Result");
  47.                       var result = resultProperty1.GetValue(context.ReturnValue);
  48.                       await (Task)genericSetMethod.Invoke(this, new object[] { cacheKeyWithParams, result });
  49.                   }
  50.               }
  51.           }
  52.           else
  53.           {
  54.               await next(context);
  55.           }
  56.       }
  57.       private string GenerateCacheKey(AspectContext context)
  58.       {
  59.           var keyBuilder = new System.Text.StringBuilder(_cacheKey);
  60.           foreach (var parameter in context.Parameters)
  61.           {
  62.               keyBuilder.Append(":").Append(FormatParameter(parameter));
  63.           }
  64.           return keyBuilder.ToString();
  65.       }
  66.       /// <summary>
  67.       /// 格式化参数(类似url过滤一下数据,: 会影响阅读)
  68.       /// </summary>
  69.       /// <param name="parameter"></param>
  70.       /// <returns></returns>
  71.       private string FormatParameter(object parameter)
  72.       {
  73.          
  74.           return JsonConvert.SerializeObject(parameter).Replace(":", "=").Replace("{", "").Replace("}", "").Replace(""", "").Replace(",", "&");
  75.       }
  76.       /// <summary>
  77.       /// 将返回值转换为原有类型
  78.       /// </summary>
  79.       /// <param name="result"></param>
  80.       /// <param name="returnType"></param>
  81.       /// <returns></returns>
  82.       private object ConvertToReturnType(object result, Type returnType)
  83.       {
  84.           Type taskResultType = returnType.GetGenericArguments()[0];
  85.           return typeof(Task).GetMethod(nameof(Task.FromResult))
  86.                              .MakeGenericMethod(taskResultType)
  87.                              .Invoke(null, new[] { result });
  88.       }
  89.       async Task<T> GetAsync<T>(string key)
  90.       {
  91.           var result = await RedisHelper.GetAsync<T>(key);
  92.           return result;
  93.       }
  94.       async Task SetAsync<T>(string cacheKey, T data)
  95.       {
  96.           if (data != null)
  97.           {
  98.               await RedisHelper.SetAsync(cacheKey, data, _expireSeconds);
  99.           }
  100.       }
  101.   }
复制代码
这样就简单实现了
只需要在方法上加注解, 一定要加virtual
  1.      //一定要加virtual
  2.      [RedisInterceptor("school")]
  3.      public virtual async Task<List<string>> SelectAsync(Guid[] schoolId)
  4.      {
  5.          ///业务
  6.          return new();
  7.      }
复制代码
QQ群: 929412850 (Byte.Core 框架交流群)
未经作者同意,禁止转发
   

来源:https://www.cnblogs.com/wxhwpmdyz/p/18397527
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具