diff --git a/AElf.ExceptionHandler/AOPExceptionModule.cs b/AElf.ExceptionHandler/AOPExceptionModule.cs index 2ce47f6..88c7d57 100644 --- a/AElf.ExceptionHandler/AOPExceptionModule.cs +++ b/AElf.ExceptionHandler/AOPExceptionModule.cs @@ -1,5 +1,6 @@ using System.Collections.Concurrent; using Microsoft.Extensions.DependencyInjection; +using Orleans; using Volo.Abp; using Volo.Abp.Modularity; @@ -10,9 +11,10 @@ public class AOPExceptionModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddTransient() - .AddTransient() - .AddSingleton>() - .AddSingleton>>(); + .AddTransient() + .AddSingleton>() + .AddSingleton>>() + .AddSingleton(); context.Services.OnRegistered(options => { @@ -31,4 +33,4 @@ public override void ConfigureServices(ServiceConfigurationContext context) } }); } -} +} \ No newline at end of file diff --git a/AElf.ExceptionHandler/AttributeCallFilter.cs b/AElf.ExceptionHandler/AttributeCallFilter.cs new file mode 100644 index 0000000..50f944c --- /dev/null +++ b/AElf.ExceptionHandler/AttributeCallFilter.cs @@ -0,0 +1,64 @@ +using Microsoft.Extensions.DependencyInjection; +using Orleans; +using Orleans.Serialization.Invocation; + +namespace AElf.ExceptionHandler; + +public class AttributeCallFilter : IIncomingGrainCallFilter +{ + public async Task Invoke(IIncomingGrainCallContext context) + { + if (context.ImplementationMethod.IsDefined(typeof(ExceptionHandlerAttribute), true)) + { + var exceptionHandler = context.TargetContext.ActivationServices.GetService(); + + if (exceptionHandler == null) + { + throw new Exception("ExceptionHandler is not registered."); + } + + var arguments = new object?[context.Request.GetArgumentCount()]; + for (var i = 0; i < context.Request.GetArgumentCount(); ++i) + { + arguments[i] = context.Request.GetArgument(i); + } + + var methodExecutionArgs = new MethodExecutionArgs + { + TargetObject = context.Grain, + MethodInfo = context.ImplementationMethod, + Arguments = arguments!, + ReturnValue = null, + Exception = null, + Invocation = async () => + { + await context.Invoke(); + } + }; + + await exceptionHandler.InterceptAsync(methodExecutionArgs); + + if (methodExecutionArgs.Exception != null) + { + context.Response = new ExceptionResponse + { + Exception = methodExecutionArgs.Exception + }; + } + else + { + if (methodExecutionArgs.ReturnValue != null) + { + var responseType = typeof(Response<>).MakeGenericType(methodExecutionArgs.ReturnValue.GetType()); + var response = Activator.CreateInstance(responseType); + responseType.GetProperty("Result")?.SetValue(response, methodExecutionArgs.ReturnValue); + context.Response = (Response)response!; + } + } + } + else + { + await context.Invoke(); + } + } +} \ No newline at end of file diff --git a/AElf.ExceptionHandler/ExceptionHandler.cs b/AElf.ExceptionHandler/ExceptionHandler.cs index e46160c..f31543f 100644 --- a/AElf.ExceptionHandler/ExceptionHandler.cs +++ b/AElf.ExceptionHandler/ExceptionHandler.cs @@ -1,10 +1,11 @@ using System.Collections.Concurrent; using System.Linq.Expressions; using System.Reflection; +using Volo.Abp.DependencyInjection; namespace AElf.ExceptionHandler; -public class ExceptionHandler : IInterceptor +public class ExceptionHandler : ITransientDependency, IInterceptor { private readonly ConcurrentDictionary MethodCache; private readonly ConcurrentDictionary> FinallyCache; @@ -162,6 +163,7 @@ private bool HandleInnerException(Exception exception, MethodExecutionArgs args, if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Rethrow) { + args.Exception = exception; throw exception; } @@ -172,9 +174,12 @@ private bool HandleInnerException(Exception exception, MethodExecutionArgs args, if(flowBehavior.ExceptionHandlingStrategy == ExceptionHandlingStrategy.Throw) { - throw (Exception)flowBehavior.ReturnValue!; + var newException = (Exception)flowBehavior.ReturnValue!; + args.Exception = newException; + throw newException; } - + + args.Exception = null; args.ReturnValue = flowBehavior.ReturnValue; return true; } diff --git a/AElf.ExceptionHandler/MethodExecutionArgs.cs b/AElf.ExceptionHandler/MethodExecutionArgs.cs index b10c664..fdf81fc 100644 --- a/AElf.ExceptionHandler/MethodExecutionArgs.cs +++ b/AElf.ExceptionHandler/MethodExecutionArgs.cs @@ -9,4 +9,5 @@ public class MethodExecutionArgs public object[] Arguments { get; set; } public object? ReturnValue { get; set; } public Func Invocation { get; set; } + public Exception? Exception { get; set; } } \ No newline at end of file