using ZhonTai.Common.Attributes; using ZhonTai.Common.Domain.Dto; using Castle.DynamicProxy; using FreeSql; using System.Linq; using System.Threading.Tasks; namespace ZhonTai.Plate.Admin.Domain { public class TransactionAsyncInterceptor : IAsyncInterceptor { private 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 InternalInterceptAsynchronous(IInvocation invocation) { TResult result; if (TryBegin(invocation)) { try { invocation.Proceed(); result = await (Task)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)invocation.ReturnValue; } return result; } /// /// 拦截同步执行的方法 /// /// public void InterceptSynchronous(IInvocation invocation) { if (TryBegin(invocation)) { try { invocation.Proceed(); var result = invocation.ReturnValue; if (result is IResponseOutput res && !res.Success) { _unitOfWork.Rollback(); } else { _unitOfWork.Commit(); } } catch { _unitOfWork.Rollback(); throw; } finally { _unitOfWork.Dispose(); } } else { invocation.Proceed(); } } /// /// 拦截返回结果为Task的方法 /// /// public void InterceptAsynchronous(IInvocation invocation) { if (TryBegin(invocation)) { invocation.ReturnValue = InternalInterceptAsynchronous(invocation); } else { invocation.Proceed(); } } /// /// 拦截返回结果为Task的方法 /// /// /// public void InterceptAsynchronous(IInvocation invocation) { invocation.ReturnValue = InternalInterceptAsynchronous(invocation); } } }