TransactionAsyncInterceptor.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using ZhonTai.Common.Attributes;
  2. using ZhonTai.Common.Domain.Dto;
  3. using Castle.DynamicProxy;
  4. using FreeSql;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. namespace ZhonTai.Plate.Admin.Domain
  8. {
  9. public class TransactionAsyncInterceptor : IAsyncInterceptor
  10. {
  11. private IUnitOfWork _unitOfWork;
  12. private readonly MyUnitOfWorkManager _unitOfWorkManager;
  13. public TransactionAsyncInterceptor(MyUnitOfWorkManager unitOfWorkManager)
  14. {
  15. _unitOfWorkManager = unitOfWorkManager;
  16. }
  17. private bool TryBegin(IInvocation invocation)
  18. {
  19. var method = invocation.MethodInvocationTarget ?? invocation.Method;
  20. var attribute = method.GetCustomAttributes(typeof(TransactionAttribute), false).FirstOrDefault();
  21. if (attribute is TransactionAttribute transaction)
  22. {
  23. _unitOfWork = _unitOfWorkManager.Begin(transaction.Propagation, transaction.IsolationLevel);
  24. return true;
  25. }
  26. return false;
  27. }
  28. private async Task InternalInterceptAsynchronous(IInvocation invocation)
  29. {
  30. //string methodName =
  31. // $"{invocation.MethodInvocationTarget.DeclaringType?.FullName}.{invocation.Method.Name}()";
  32. //int? hashCode = _unitOfWork.GetHashCode();
  33. invocation.Proceed();
  34. try
  35. {
  36. //处理Task返回一个null值的情况会导致空指针
  37. if (invocation.ReturnValue != null)
  38. {
  39. await (Task)invocation.ReturnValue;
  40. }
  41. _unitOfWork.Commit();
  42. }
  43. catch (System.Exception)
  44. {
  45. _unitOfWork.Rollback();
  46. throw;
  47. }
  48. finally
  49. {
  50. _unitOfWork.Dispose();
  51. }
  52. }
  53. private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
  54. {
  55. TResult result;
  56. if (TryBegin(invocation))
  57. {
  58. try
  59. {
  60. invocation.Proceed();
  61. result = await (Task<TResult>)invocation.ReturnValue;
  62. if (result is IResponseOutput res && !res.Success)
  63. {
  64. _unitOfWork.Rollback();
  65. }
  66. else
  67. {
  68. _unitOfWork.Commit();
  69. }
  70. }
  71. catch (System.Exception)
  72. {
  73. _unitOfWork.Rollback();
  74. throw;
  75. }
  76. finally
  77. {
  78. _unitOfWork.Dispose();
  79. }
  80. }
  81. else
  82. {
  83. invocation.Proceed();
  84. result = await (Task<TResult>)invocation.ReturnValue;
  85. }
  86. return result;
  87. }
  88. /// <summary>
  89. /// 拦截同步执行的方法
  90. /// </summary>
  91. /// <param name="invocation"></param>
  92. public void InterceptSynchronous(IInvocation invocation)
  93. {
  94. if (TryBegin(invocation))
  95. {
  96. try
  97. {
  98. invocation.Proceed();
  99. var result = invocation.ReturnValue;
  100. if (result is IResponseOutput res && !res.Success)
  101. {
  102. _unitOfWork.Rollback();
  103. }
  104. else
  105. {
  106. _unitOfWork.Commit();
  107. }
  108. }
  109. catch
  110. {
  111. _unitOfWork.Rollback();
  112. throw;
  113. }
  114. finally
  115. {
  116. _unitOfWork.Dispose();
  117. }
  118. }
  119. else
  120. {
  121. invocation.Proceed();
  122. }
  123. }
  124. /// <summary>
  125. /// 拦截返回结果为Task的方法
  126. /// </summary>
  127. /// <param name="invocation"></param>
  128. public void InterceptAsynchronous(IInvocation invocation)
  129. {
  130. if (TryBegin(invocation))
  131. {
  132. invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
  133. }
  134. else
  135. {
  136. invocation.Proceed();
  137. }
  138. }
  139. /// <summary>
  140. /// 拦截返回结果为Task<TResult>的方法
  141. /// </summary>
  142. /// <typeparam name="TResult"></typeparam>
  143. /// <param name="invocation"></param>
  144. public void InterceptAsynchronous<TResult>(IInvocation invocation)
  145. {
  146. invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
  147. }
  148. }
  149. }