平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GlobalDispatchProxy.cs 16 KiB

4 月之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. 
  2. //
  3. namespace SafeCampus.Plugin.Aop;
  4. /// <summary>
  5. /// Aop
  6. /// 这里没有继承IGlobalDispatchProxy是因为IGlobalDispatchProxy会把一些没有必要的方法也aop了
  7. /// </summary>
  8. public class GlobalDispatchProxy : AspectDispatchProxy, IDispatchProxy
  9. {
  10. /// <summary>
  11. /// 当前服务实例
  12. /// </summary>
  13. public object Target { get; set; }
  14. /// <summary>
  15. /// 服务提供器,可以用来解析服务,如:Services.GetService()
  16. /// </summary>
  17. public IServiceProvider Services { get; set; }
  18. /// <summary>
  19. /// 方法
  20. /// </summary>
  21. /// <param name="method"></param>
  22. /// <param name="args"></param>
  23. /// <returns></returns>
  24. /// <exception cref="NotImplementedException"></exception>
  25. public override object Invoke(MethodInfo method, object[] args)
  26. {
  27. //如果不带返回值
  28. if (method.ReturnType == typeof(void))
  29. {
  30. After(method, null, args);
  31. return method.Invoke(Target, args);//直接返回
  32. }
  33. var result = Before(method, args);//方法执行之前判断是否有缓存的数据
  34. if (result == null) result = method.Invoke(Target, args);//如果没有缓存就执行方法返回数据
  35. After(method, result, args);//方法执行之后干的事
  36. return result;//返回结果
  37. }
  38. /// <summary>
  39. /// 异步无返回值
  40. /// </summary>
  41. /// <param name="method"></param>
  42. /// <param name="args"></param>
  43. /// <returns></returns>
  44. /// <exception cref="NotImplementedException"></exception>
  45. public override async Task InvokeAsync(MethodInfo method, object[] args)
  46. {
  47. var task = method.Invoke(Target, args) as Task;
  48. await task;
  49. After(method, null, args);
  50. }
  51. /// <summary>
  52. /// 异步带返回值
  53. /// </summary>
  54. /// <typeparam name="T"></typeparam>
  55. /// <param name="method"></param>
  56. /// <param name="args"></param>
  57. /// <returns></returns>
  58. /// <exception cref="NotImplementedException"></exception>
  59. public override async Task<T> InvokeAsyncT<T>(MethodInfo method, object[] args)
  60. {
  61. var result = Before(method, args);//方法执行之前判断是否有缓存的数据
  62. if (result == null)
  63. {
  64. var taskT = method.Invoke(Target, args) as Task<T>;
  65. result = await taskT;//如果没有缓存就执行方法返回数据
  66. }
  67. After(method, result, args);//方法执行之后干的事
  68. return result;//返回结果
  69. }
  70. /// <summary>
  71. /// 方法执行之后
  72. /// </summary>
  73. /// <param name="method">方法</param>
  74. /// <param name="returnValue">返回值</param>
  75. /// <param name="args">参数列表</param>
  76. private void After(MethodInfo method, object returnValue, object[] args)
  77. {
  78. RecordCache(method, args, returnValue);//记录返回值到缓存
  79. }
  80. /// <summary>
  81. /// 方法执行之前
  82. /// </summary>
  83. /// <param name="method">方法</param>
  84. /// <param name="args">参数列表</param>
  85. /// <returns></returns>
  86. private dynamic Before(MethodInfo method, object[] args)
  87. {
  88. var cacheData = CheckCache(method, args);//检查缓存
  89. if (cacheData != null) { return cacheData; }//如果缓存有数据直接返回
  90. return null;//默认返回空
  91. }
  92. /// <summary>
  93. /// 检查缓存里是否有数据
  94. /// </summary>
  95. /// <param name="method">方法</param>
  96. /// <param name="args">参数列表</param>
  97. private dynamic CheckCache(MethodInfo method, object[] args)
  98. {
  99. var cacheAttribute = method.GetActualCustomAttribute<CacheAttribute>(Target);//读取缓存特性
  100. //判断需不需要读取缓存
  101. if (cacheAttribute != null)
  102. {
  103. var redisManager = Services.GetService<ISimpleCacheService>();// 获取redis服务
  104. var cacheKey = cacheAttribute.CustomKeyValue
  105. ?? CustomCacheKey(cacheAttribute.KeyPrefix, method, args);//如果redisKey值,如果有自定义值就用自定义Key,否则以前缀+系统自动生成的Key
  106. string cacheValue;
  107. if (cacheAttribute.StoreType == CacheConst.CACHE_HASH)//如果存的是Hash值
  108. {
  109. cacheValue = redisManager.HashGet<string>(cacheKey, args[0].ToString())[0];//从redis获取Hash数据取第一个,注意是 string 类型
  110. }
  111. else
  112. {
  113. cacheValue = redisManager.Get<string>(cacheKey);//注意是 string 类型,方法GetValue
  114. }
  115. if (!string.IsNullOrEmpty(cacheValue))//如果返回值不是空
  116. {
  117. //if (cacheAttribute.IsDelete)//判断是否是删除操作
  118. //{
  119. // if (cacheAttribute.StoreType == RedisConst.Cache_Hash)//如果是Hash
  120. // {
  121. // _redisManager.HashDel<string>(cacheKey, new string[] { args[0].ToString() });
  122. // }
  123. // else
  124. // {
  125. // //删除Redis整个KEY
  126. // _redisManager.Remove(cacheKey);
  127. // }
  128. //}
  129. //将当前获取到的缓存值,赋值给当前执行方法
  130. Type returnType;
  131. if (typeof(Task).IsAssignableFrom(method.ReturnType))
  132. {
  133. returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault();
  134. }
  135. else
  136. {
  137. returnType = method.ReturnType;
  138. }
  139. if (!returnType.IsPrimitive && returnType != typeof(string))//判断返回类型是否原生类型并且不是string
  140. {
  141. dynamic result = JsonConvert.DeserializeObject(cacheValue, returnType);//序列化数据
  142. return result;
  143. }
  144. return cacheValue;
  145. }
  146. }
  147. return null;
  148. }
  149. /// <summary>
  150. /// 写数据到缓存
  151. /// </summary>
  152. /// <param name="method">方法</param>
  153. /// <param name="args">参数列表</param>
  154. /// <param name="returnValue">返回值</param>
  155. private void RecordCache(MethodInfo method, object[] args, object returnValue)
  156. {
  157. var cacheAttribute = method.GetActualCustomAttribute<CacheAttribute>(Target);
  158. if (cacheAttribute != null)
  159. {
  160. //获取自定义缓存键
  161. var cacheKey = cacheAttribute.CustomKeyValue ?? CustomCacheKey(cacheAttribute.KeyPrefix, method, args);
  162. if (!string.IsNullOrWhiteSpace(cacheKey))//如果有key
  163. {
  164. var redisManager = Services.GetService<ISimpleCacheService>();// 获取redis服务
  165. if (cacheAttribute.IsDelete)//判断是否是删除操作
  166. {
  167. //删除Redis整个KEY
  168. redisManager.Remove(cacheKey);
  169. }
  170. else
  171. {
  172. if (returnValue == null) { return; }
  173. if (cacheAttribute.StoreType == CacheConst.CACHE_HASH)//如果是hash类型的
  174. {
  175. //插入到hash,这里规定是方法的第一个参数
  176. redisManager.HashAdd(cacheKey, args[0].ToString(), returnValue);
  177. }
  178. else
  179. {
  180. if (cacheAttribute.AbsoluteExpiration != null)//如果有超时时间
  181. {
  182. redisManager.Set(cacheKey, returnValue, cacheAttribute.AbsoluteExpiration.Value);//插入redis
  183. }
  184. else
  185. {
  186. redisManager.Set(cacheKey, returnValue);//插入redis
  187. }
  188. }
  189. }
  190. }
  191. }
  192. }
  193. /// <summary>
  194. /// 自定义缓存Key
  195. /// </summary>
  196. /// <param name="prefix">前缀</param>
  197. /// <param name="method">方法</param>
  198. /// <param name="args">参数</param>
  199. /// <returns></returns>
  200. protected string CustomCacheKey(string prefix, MethodInfo method, object[] args)
  201. {
  202. var key = prefix;//前缀
  203. var methodArguments = args.Select(GetCacheKey.GetArgumentValue).Take(3).ToList();//获取参数列表,最多三个
  204. if (!string.IsNullOrEmpty(key))//如果制定了前缀
  205. {
  206. foreach (var param in methodArguments)//遍历参数列表
  207. {
  208. key = $"{key}{param}:";//生成KEY
  209. }
  210. }
  211. else
  212. {
  213. var typeName = Target.GetType().Name;//获取实例名
  214. var methodName = method.Name;//获取方法名
  215. key = $"{CacheConst.CACHE_PREFIX_WEB}{typeName}:{methodName}:";//生成Key
  216. foreach (var param in methodArguments)//遍历参数列表
  217. {
  218. key = $"{key}{param}:";//生成加上参数的KEY
  219. }
  220. }
  221. return key.TrimEnd(':');
  222. }
  223. }
  224. /// <summary>
  225. /// 获取缓存Key
  226. /// </summary>
  227. internal static class GetCacheKey
  228. {
  229. /// <summary>
  230. /// object 转 string
  231. /// </summary>
  232. /// <param name="arg"></param>
  233. /// <returns></returns>
  234. public static string GetArgumentValue(object arg)
  235. {
  236. if (arg is DateTime || arg is DateTime)
  237. return ((DateTime)arg).ToString("yyyyMMddHHmmss");
  238. if (arg is string || arg is ValueType || arg is Nullable)
  239. return arg.ToString();
  240. if (arg != null)
  241. {
  242. if (arg is Expression)
  243. {
  244. var obj = arg as Expression;
  245. var result = Resolve(obj);
  246. return MD5Encryption.Encrypt(result);
  247. }
  248. if (arg.GetType().IsClass)
  249. {
  250. return MD5Encryption.Encrypt(JsonConvert.SerializeObject(arg));
  251. }
  252. }
  253. return string.Empty;
  254. }
  255. private static string Resolve(Expression expression)
  256. {
  257. if (expression is LambdaExpression)
  258. {
  259. var lambda = expression as LambdaExpression;
  260. expression = lambda.Body;
  261. return Resolve(expression);
  262. }
  263. if (expression is BinaryExpression)
  264. {
  265. var binary = expression as BinaryExpression;
  266. if (binary.Left is MemberExpression && binary.Right is ConstantExpression)//解析x=>x.Name=="123" x.Age==123这类
  267. return ResolveFunc(binary.Left, binary.Right, binary.NodeType);
  268. if (binary.Left is MethodCallExpression && binary.Right is ConstantExpression)//解析x=>x.Name.Contains("xxx")==false这类的
  269. {
  270. var value = (binary.Right as ConstantExpression).Value;
  271. return ResolveLinqToObject(binary.Left, value, binary.NodeType);
  272. }
  273. if (binary.Left is MemberExpression && binary.Right is MemberExpression
  274. || binary.Left is MemberExpression && binary.Right is UnaryExpression)//解析x=>x.Date==DateTime.Now这种
  275. {
  276. var lambda = Expression.Lambda(binary.Right);
  277. var fn = lambda.Compile();
  278. var value = Expression.Constant(fn.DynamicInvoke(null), binary.Right.Type);
  279. return ResolveFunc(binary.Left, value, binary.NodeType);
  280. }
  281. }
  282. if (expression is UnaryExpression)
  283. {
  284. var unary = expression as UnaryExpression;
  285. if (unary.Operand is MethodCallExpression)//解析!x=>x.Name.Contains("xxx")或!array.Contains(x.Name)这类
  286. return ResolveLinqToObject(unary.Operand, false);
  287. if (unary.Operand is MemberExpression && unary.NodeType == ExpressionType.Not)//解析x=>!x.isDeletion这样的
  288. {
  289. var constant = Expression.Constant(false);
  290. return ResolveFunc(unary.Operand, constant, ExpressionType.Equal);
  291. }
  292. }
  293. if (expression is MemberExpression && expression.NodeType == ExpressionType.MemberAccess)//解析x=>x.isDeletion这样的
  294. {
  295. var member = expression as MemberExpression;
  296. var constant = Expression.Constant(true);
  297. return ResolveFunc(member, constant, ExpressionType.Equal);
  298. }
  299. if (expression is MethodCallExpression)//x=>x.Name.Contains("xxx")或array.Contains(x.Name)这类
  300. {
  301. var methodcall = expression as MethodCallExpression;
  302. return ResolveLinqToObject(methodcall, true);
  303. }
  304. //已经修改过代码body应该不会是null值了
  305. if (!(expression is BinaryExpression body))
  306. return string.Empty;
  307. var @operator = GetOperator(body.NodeType);
  308. var left = Resolve(body.Left);
  309. var right = Resolve(body.Right);
  310. var result = string.Format("({0} {1} {2})", left, @operator, right);
  311. return result;
  312. }
  313. private static string ResolveFunc(Expression left, Expression right, ExpressionType expressiontype)
  314. {
  315. var name = (left as MemberExpression).Member.Name;
  316. var value = (right as ConstantExpression).Value;
  317. var @operator = GetOperator(expressiontype);
  318. return name + @operator + value;
  319. }
  320. private static string ResolveLinqToObject(Expression expression, object value, ExpressionType? expressiontype = null)
  321. {
  322. var methodCall = expression as MethodCallExpression;
  323. var methodName = methodCall.Method.Name;
  324. switch (methodName)
  325. {
  326. case "Contains":
  327. return methodCall.Object != null ? Like(methodCall) : In(methodCall, value);
  328. case "Count":
  329. return Len(methodCall, value, expressiontype.Value);
  330. case "LongCount":
  331. return Len(methodCall, value, expressiontype.Value);
  332. default:
  333. throw new Exception(string.Format("不支持{0}方法的查找!", methodName));
  334. }
  335. }
  336. private static string GetOperator(ExpressionType expressiontype)
  337. {
  338. return expressiontype switch
  339. {
  340. ExpressionType.And => "and",
  341. ExpressionType.AndAlso => "and",
  342. ExpressionType.Or => "or",
  343. ExpressionType.OrElse => "or",
  344. ExpressionType.Equal => "=",
  345. ExpressionType.NotEqual => "<>",
  346. ExpressionType.LessThan => "<",
  347. ExpressionType.LessThanOrEqual => "<=",
  348. ExpressionType.GreaterThan => ">",
  349. ExpressionType.GreaterThanOrEqual => ">=",
  350. _ => throw new Exception(string.Format("不支持{0}此种运算符查找!" + expressiontype))
  351. };
  352. }
  353. private static string In(MethodCallExpression expression, object isTrue)
  354. {
  355. var argument1 = (expression.Arguments[0] as MemberExpression).Expression as ConstantExpression;
  356. var argument2 = expression.Arguments[1] as MemberExpression;
  357. var fieldArray = argument1.Value.GetType().GetFields().First();
  358. var array = fieldArray.GetValue(argument1.Value) as object[];
  359. var setInPara = new List<string>();
  360. for (var i = 0; i < array.Length; i++)
  361. {
  362. var value = array[i].ToString();
  363. setInPara.Add(value);
  364. }
  365. var name = argument2.Member.Name;
  366. var @operator = Convert.ToBoolean(isTrue) ? "in" : " not in";
  367. var compName = string.Join(",", setInPara);
  368. var result = string.Format("{0} {1} ({2})", name, @operator, compName);
  369. return result;
  370. }
  371. private static string Like(MethodCallExpression expression)
  372. {
  373. var temp = expression.Arguments[0];
  374. var lambda = Expression.Lambda(temp);
  375. var fn = lambda.Compile();
  376. var tempValue = Expression.Constant(fn.DynamicInvoke(null), temp.Type);
  377. var value = string.Format("%{0}%", tempValue);
  378. var name = (expression.Object as MemberExpression).Member.Name;
  379. var result = string.Format("{0} like {1}", name, value);
  380. return result;
  381. }
  382. private static string Len(MethodCallExpression expression, object value, ExpressionType expressiontype)
  383. {
  384. object name = (expression.Arguments[0] as MemberExpression).Member.Name;
  385. var @operator = GetOperator(expressiontype);
  386. var result = string.Format("len({0}){1}{2}", name, @operator, value);
  387. return result;
  388. }
  389. }