|
@@ -0,0 +1,154 @@
|
|
|
+using System.Threading.Tasks;
|
|
|
+using Castle.DynamicProxy;
|
|
|
+using FreeSql;
|
|
|
+using Admin.Core.Common.Extensions;
|
|
|
+using Admin.Core.Common.Output;
|
|
|
+using Admin.Core.Common.Attributes;
|
|
|
+using Admin.Core.Repository;
|
|
|
+using System.Linq;
|
|
|
+
|
|
|
+namespace Admin.Core.Aop
|
|
|
+{
|
|
|
+ public class TransactionAsyncInterceptor : IAsyncInterceptor
|
|
|
+ {
|
|
|
+ IUnitOfWork _unitOfWork;
|
|
|
+ private readonly MyUnitOfWorkManager _unitOfWorkManager;
|
|
|
+
|
|
|
+ public TransactionAsyncInterceptor(MyUnitOfWorkManager unitOfWorkManager)
|
|
|
+ {
|
|
|
+ _unitOfWorkManager = unitOfWorkManager;
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool TryBegin(IInvocation invocation)
|
|
|
+ {
|
|
|
+ var method = invocation.MethodInvocationTarget ?? invocation.Method;
|
|
|
+ var attribute = method.GetCustomAttributes(typeof(TransactionAttribute), false).FirstOrDefault();
|
|
|
+ if (attribute is TransactionAttribute transaction)
|
|
|
+ {
|
|
|
+ _unitOfWork = _unitOfWorkManager.Begin(transaction.Propagation, transaction.IsolationLevel);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task InternalInterceptAsynchronous(IInvocation invocation)
|
|
|
+ {
|
|
|
+ //string methodName =
|
|
|
+ // $"{invocation.MethodInvocationTarget.DeclaringType?.FullName}.{invocation.Method.Name}()";
|
|
|
+ //int? hashCode = _unitOfWork.GetHashCode();
|
|
|
+
|
|
|
+ invocation.Proceed();
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //处理Task返回一个null值的情况会导致空指针
|
|
|
+ if (invocation.ReturnValue != null)
|
|
|
+ {
|
|
|
+ await (Task)invocation.ReturnValue;
|
|
|
+ }
|
|
|
+ _unitOfWork.Commit();
|
|
|
+ }
|
|
|
+ catch (System.Exception)
|
|
|
+ {
|
|
|
+ _unitOfWork.Rollback();
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _unitOfWork.Dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
|
|
|
+ {
|
|
|
+ TResult result;
|
|
|
+ if (TryBegin(invocation))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ invocation.Proceed();
|
|
|
+ result = await (Task<TResult>)invocation.ReturnValue;
|
|
|
+ if (result is IResponseOutput res && !res.Success)
|
|
|
+ {
|
|
|
+ _unitOfWork.Rollback();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _unitOfWork.Commit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (System.Exception)
|
|
|
+ {
|
|
|
+ _unitOfWork.Rollback();
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _unitOfWork.Dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ invocation.Proceed();
|
|
|
+ result = await (Task<TResult>)invocation.ReturnValue;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 拦截同步执行的方法
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="invocation"></param>
|
|
|
+ public void InterceptSynchronous(IInvocation invocation)
|
|
|
+ {
|
|
|
+ if (TryBegin(invocation))
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ invocation.Proceed();
|
|
|
+ _unitOfWork.Commit();
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ _unitOfWork.Rollback();
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ finally
|
|
|
+ {
|
|
|
+ _unitOfWork.Dispose();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ invocation.Proceed();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 拦截返回结果为Task的方法
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="invocation"></param>
|
|
|
+ public void InterceptAsynchronous(IInvocation invocation)
|
|
|
+ {
|
|
|
+ if (TryBegin(invocation))
|
|
|
+ {
|
|
|
+ invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ invocation.Proceed();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 拦截返回结果为Task<TResult>的方法
|
|
|
+ /// </summary>
|
|
|
+ /// <typeparam name="TResult"></typeparam>
|
|
|
+ /// <param name="invocation"></param>
|
|
|
+ public void InterceptAsynchronous<TResult>(IInvocation invocation)
|
|
|
+ {
|
|
|
+ invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|