Skip to content

Commit f6b67cf

Browse files
authored
Add aspect exception wrapper (#148)
* Add aspect exception wrapper * Fix AspectCore.Extensions.Autofac.Sample * Fix samples * Fix issue 138 * update version * Fix AspectExceptionWrapper service
1 parent ee8aff7 commit f6b67cf

File tree

29 files changed

+138
-76
lines changed

29 files changed

+138
-76
lines changed

build/version.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<Project>
22
<PropertyGroup>
33
<VersionMajor>1</VersionMajor>
4-
<VersionMinor>0</VersionMinor>
5-
<VersionPatch>1</VersionPatch>
4+
<VersionMinor>1</VersionMinor>
5+
<VersionPatch>0</VersionPatch>
66
<VersionQuality></VersionQuality>
77
<VersionPrefix>$(VersionMajor).$(VersionMinor).$(VersionPatch)</VersionPrefix>
88
</PropertyGroup>

core/src/AspectCore.Abstractions/Configuration/IAspectConfiguration.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ public interface IAspectConfiguration
1111
InterceptorCollection Interceptors { get; }
1212

1313
NonAspectPredicateCollection NonAspectPredicates { get; }
14+
15+
bool ThrowAspectException { get; set; }
1416
}
1517
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using AspectCore.Configuration;
3+
4+
namespace AspectCore.DynamicProxy
5+
{
6+
[NonAspect]
7+
public class AspectExceptionWrapper : IAspectExceptionWrapper
8+
{
9+
private readonly IAspectConfiguration _configuration;
10+
11+
public AspectExceptionWrapper(IAspectConfiguration configuration)
12+
{
13+
_configuration = configuration;
14+
}
15+
16+
public Exception Wrap(AspectContext aspectContext, Exception exception)
17+
{
18+
if (!_configuration.ThrowAspectException)
19+
{
20+
return exception;
21+
}
22+
23+
if (exception is AspectInvocationException aspectInvocationException)
24+
{
25+
return aspectInvocationException;
26+
}
27+
28+
return new AspectInvocationException(aspectContext, exception);
29+
}
30+
}
31+
}

core/src/AspectCore.Abstractions/DynamicProxy/AspectInvocationException.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class AspectInvocationException : Exception
99
public AspectInvocationException(AspectContext aspectContext, Exception innerException)
1010
: base($"Exception has been thrown by the aspect of an invocation. ---> {innerException?.Message}.", innerException)
1111
{
12+
AspectContext = aspectContext;
1213
}
1314
}
1415
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace AspectCore.DynamicProxy
4+
{
5+
public interface IAspectExceptionWrapper
6+
{
7+
Exception Wrap(AspectContext aspectContext, Exception exception);
8+
}
9+
}

core/src/AspectCore.Core/Configuration/AspectConfiguration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ public sealed class AspectConfiguration : IAspectConfiguration
1010

1111
public NonAspectPredicateCollection NonAspectPredicates { get; }
1212

13+
public bool ThrowAspectException { get; set; }
14+
1315
public AspectConfiguration()
1416
{
17+
ThrowAspectException = true;
1518
ValidationHandlers = new AspectValidationHandlerCollection().AddDefault(this);
1619
Interceptors = new InterceptorCollection();
1720
NonAspectPredicates = new NonAspectPredicateCollection().AddDefault();

core/src/AspectCore.Core/DynamicProxy/AspectActivator.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ internal sealed class AspectActivator : IAspectActivator
1111
{
1212
private readonly IAspectContextFactory _aspectContextFactory;
1313
private readonly IAspectBuilderFactory _aspectBuilderFactory;
14+
private readonly IAspectExceptionWrapper _aspectExceptionWrapper;
1415

15-
public AspectActivator(IAspectContextFactory aspectContextFactory, IAspectBuilderFactory aspectBuilderFactory)
16+
public AspectActivator(IAspectContextFactory aspectContextFactory, IAspectBuilderFactory aspectBuilderFactory, IAspectExceptionWrapper aspectExceptionWrapper)
1617
{
1718
_aspectContextFactory = aspectContextFactory;
1819
_aspectBuilderFactory = aspectBuilderFactory;
20+
_aspectExceptionWrapper = aspectExceptionWrapper;
1921
}
2022

2123
public TResult Invoke<TResult>(AspectActivatorContext activatorContext)
@@ -26,18 +28,19 @@ public TResult Invoke<TResult>(AspectActivatorContext activatorContext)
2628
var aspectBuilder = _aspectBuilderFactory.Create(context);
2729
var task = aspectBuilder.Build()(context);
2830
if (task.IsFaulted)
29-
throw context.InvocationException(task.Exception.InnerException);
31+
throw _aspectExceptionWrapper.Wrap(context, task.Exception.InnerException);
3032
if (!task.IsCompleted)
3133
{
3234
// try to avoid potential deadlocks.
3335
NoSyncContextScope.Run(task);
3436
// task.GetAwaiter().GetResult();
3537
}
36-
return (TResult)context.ReturnValue;
38+
39+
return (TResult) context.ReturnValue;
3740
}
3841
catch (Exception ex)
3942
{
40-
throw context.InvocationException(ex);
43+
throw _aspectExceptionWrapper.Wrap(context, ex);
4144
}
4245
finally
4346
{
@@ -64,13 +67,13 @@ public async Task<TResult> InvokeTask<TResult>(AspectActivatorContext activatorC
6467
}
6568
else
6669
{
67-
throw context.InvocationException(new InvalidCastException(
70+
throw _aspectExceptionWrapper.Wrap(context, new InvalidCastException(
6871
$"Unable to cast object of type '{result.GetType()}' to type '{typeof(Task<TResult>)}'."));
6972
}
7073
}
7174
catch (Exception ex)
7275
{
73-
throw context.InvocationException(ex);
76+
throw _aspectExceptionWrapper.Wrap(context, ex);
7477
}
7578
finally
7679
{
@@ -85,11 +88,11 @@ public async ValueTask<TResult> InvokeValueTask<TResult>(AspectActivatorContext
8588
{
8689
var aspectBuilder = _aspectBuilderFactory.Create(context);
8790
await aspectBuilder.Build()(context);
88-
return await (ValueTask<TResult>)context.ReturnValue;
91+
return await (ValueTask<TResult>) context.ReturnValue;
8992
}
9093
catch (Exception ex)
9194
{
92-
throw context.InvocationException(ex);
95+
throw _aspectExceptionWrapper.Wrap(context, ex);
9396
}
9497
finally
9598
{

core/src/AspectCore.Core/DynamicProxy/AspectActivatorFactory.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ public sealed class AspectActivatorFactory : IAspectActivatorFactory
77
{
88
private readonly IAspectContextFactory _aspectContextFactory;
99
private readonly IAspectBuilderFactory _aspectBuilderFactory;
10+
private readonly IAspectExceptionWrapper _aspectExceptionWrapper;
1011

11-
public AspectActivatorFactory(IAspectContextFactory aspectContextFactory, IAspectBuilderFactory aspectBuilderFactory)
12+
public AspectActivatorFactory(IAspectContextFactory aspectContextFactory, IAspectBuilderFactory aspectBuilderFactory, IAspectExceptionWrapper aspectExceptionWrapper)
1213
{
1314
_aspectContextFactory = aspectContextFactory ?? throw new ArgumentNullException(nameof(aspectContextFactory));
1415
_aspectBuilderFactory = aspectBuilderFactory ?? throw new ArgumentNullException(nameof(aspectBuilderFactory));
16+
_aspectExceptionWrapper = aspectExceptionWrapper ?? throw new ArgumentNullException(nameof(aspectExceptionWrapper));
1517
}
1618

1719
public IAspectActivator Create()
1820
{
19-
return new AspectActivator(_aspectContextFactory, _aspectBuilderFactory);
21+
return new AspectActivator(_aspectContextFactory, _aspectBuilderFactory, _aspectExceptionWrapper);
2022
}
2123
}
22-
}
24+
}

core/src/AspectCore.Core/DynamicProxy/Extensions/AspectContextRuntimeExtensions.cs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,22 @@ public static class AspectContextRuntimeExtensions
1313

1414
internal static readonly ConcurrentDictionary<MethodInfo, MethodReflector> reflectorTable = new ConcurrentDictionary<MethodInfo, MethodReflector>();
1515

16+
public static Task AwaitIfAsync(this AspectContext aspectContext)
17+
{
18+
return AwaitIfAsync(aspectContext, aspectContext.ReturnValue);
19+
}
20+
1621
public static async Task AwaitIfAsync(this AspectContext aspectContext, object returnValue)
1722
{
1823
if (returnValue == null)
1924
{
2025
return;
2126
}
22-
if (returnValue is Task task)
23-
{
24-
try
25-
{
26-
await task;
27-
}
28-
catch (Exception ex)
29-
{
30-
throw aspectContext.InvocationException(ex);
31-
}
32-
}
33-
}
3427

35-
public static AspectInvocationException InvocationException(this AspectContext aspectContext, Exception exception)
36-
{
37-
if (exception is AspectInvocationException aspectInvocationException)
28+
if (returnValue is Task task)
3829
{
39-
return aspectInvocationException;
30+
await task;
4031
}
41-
return new AspectInvocationException(aspectContext, exception);
4232
}
4333

4434
public static bool IsAsync(this AspectContext aspectContext)
@@ -47,33 +37,44 @@ public static bool IsAsync(this AspectContext aspectContext)
4737
{
4838
throw new ArgumentNullException(nameof(aspectContext));
4939
}
40+
5041
var isAsyncFromMetaData = isAsyncCache.GetOrAdd(aspectContext.ServiceMethod, IsAsyncFromMetaData);
5142
if (isAsyncFromMetaData)
5243
{
5344
return true;
5445
}
46+
5547
if (aspectContext.ReturnValue != null)
5648
{
5749
return IsAsyncType(aspectContext.ReturnValue.GetType().GetTypeInfo());
5850
}
51+
5952
return false;
6053
}
6154

55+
public static async Task<T> UnwrapAsyncReturnValue<T>(this AspectContext aspectContext)
56+
{
57+
return (T) await UnwrapAsyncReturnValue(aspectContext);
58+
}
59+
6260
public static Task<object> UnwrapAsyncReturnValue(this AspectContext aspectContext)
6361
{
6462
if (aspectContext == null)
6563
{
6664
throw new ArgumentNullException(nameof(aspectContext));
6765
}
66+
6867
if (!aspectContext.IsAsync())
6968
{
7069
throw new AspectInvocationException(aspectContext, new InvalidOperationException("This operation only support asynchronous method."));
7170
}
71+
7272
var returnValue = aspectContext.ReturnValue;
7373
if (returnValue == null)
7474
{
7575
return null;
7676
}
77+
7778
var returnTypeInfo = returnValue.GetType().GetTypeInfo();
7879
return Unwrap(returnValue, returnTypeInfo);
7980
}
@@ -90,7 +91,7 @@ private static async Task<object> Unwrap(object value, TypeInfo valueTypeInfo)
9091
else if (valueTypeInfo.IsValueTask())
9192
{
9293
// Is there better solution to unwrap ?
93-
result = (object)(await (dynamic)value);
94+
result = (object) (await (dynamic) value);
9495
}
9596
else if (value is Task)
9697
{
@@ -111,6 +112,7 @@ private static async Task<object> Unwrap(object value, TypeInfo valueTypeInfo)
111112
{
112113
return Unwrap(result, resultTypeInfo);
113114
}
115+
114116
return result;
115117
}
116118

@@ -120,13 +122,15 @@ private static bool IsAsyncFromMetaData(MethodInfo method)
120122
{
121123
return true;
122124
}
125+
123126
if (method.IsDefined(typeof(AsyncAspectAttribute), true))
124127
{
125128
if (method.ReturnType == typeof(object))
126129
{
127130
return true;
128131
}
129132
}
133+
130134
return false;
131135
}
132136

@@ -137,14 +141,17 @@ private static bool IsAsyncType(TypeInfo typeInfo)
137141
{
138142
return true;
139143
}
144+
140145
if (typeInfo.IsTaskWithResult())
141146
{
142147
return true;
143148
}
149+
144150
if (typeInfo.IsValueTask())
145151
{
146152
return true;
147153
}
154+
148155
return false;
149156
}
150157
}

core/src/AspectCore.Core/Injector/ServiceContainer.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ private void AddInternalServices()
9999
Scopeds.AddType<IParameterInterceptorSelector, ParameterInterceptorSelector>();
100100
if (!Contains(typeof(IAspectCachingProvider)))
101101
Singletons.AddType<IAspectCachingProvider, AspectCachingProvider>();
102+
if (!Contains(typeof(IAspectExceptionWrapper)))
103+
Singletons.AddType<IAspectExceptionWrapper, AspectExceptionWrapper>();
102104
}
103105

104106
public int Count => _collection.Count;

0 commit comments

Comments
 (0)