Skip to content

Commit 96d9a0f

Browse files
committed
First hack using the updates for Castle.Core
1 parent e315aff commit 96d9a0f

File tree

3 files changed

+52
-41
lines changed

3 files changed

+52
-41
lines changed

src/Castle.Core.AsyncInterceptor/AsyncInterceptorBase.cs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ public abstract class AsyncInterceptorBase : IAsyncInterceptor
2222
#endif
2323

2424
private static readonly MethodInfo InterceptSynchronousMethodInfo =
25-
typeof(AsyncInterceptorBase)
26-
.GetMethod(nameof(InterceptSynchronousResult), BindingFlags.Static | BindingFlags.NonPublic);
25+
typeof(AsyncInterceptorBase).GetMethod(
26+
nameof(InterceptSynchronousResult),
27+
BindingFlags.Static | BindingFlags.NonPublic);
2728

2829
private static readonly ConcurrentDictionary<Type, GenericSynchronousHandler> GenericSynchronousHandlers =
2930
new ConcurrentDictionary<Type, GenericSynchronousHandler>
@@ -50,7 +51,7 @@ void IAsyncInterceptor.InterceptSynchronous(IInvocation invocation)
5051
/// <param name="invocation">The method invocation.</param>
5152
void IAsyncInterceptor.InterceptAsynchronous(IInvocation invocation)
5253
{
53-
invocation.ReturnValue = InterceptAsync(invocation, ProceedAsynchronous);
54+
invocation.ReturnValue = InterceptAsync(invocation.GetProceedInfo(), ProceedAsynchronous);
5455
}
5556

5657
/// <summary>
@@ -60,27 +61,29 @@ void IAsyncInterceptor.InterceptAsynchronous(IInvocation invocation)
6061
/// <param name="invocation">The method invocation.</param>
6162
void IAsyncInterceptor.InterceptAsynchronous<TResult>(IInvocation invocation)
6263
{
63-
invocation.ReturnValue = InterceptAsync(invocation, ProceedAsynchronous<TResult>);
64+
invocation.ReturnValue = InterceptAsync(invocation.GetProceedInfo(), ProceedAsynchronous<TResult>);
6465
}
6566

6667
/// <summary>
6768
/// Override in derived classes to intercept method invocations.
6869
/// </summary>
69-
/// <param name="invocation">The method invocation.</param>
70-
/// <param name="proceed">The function to proceed the <paramref name="invocation"/>.</param>
70+
/// <param name="proceedInfo">The <see cref="IInvocationProceedInfo"/>.</param>
71+
/// <param name="proceed">The function to proceed the <paramref name="proceedInfo"/>.</param>
7172
/// <returns>A <see cref="Task" /> object that represents the asynchronous operation.</returns>
72-
protected abstract Task InterceptAsync(IInvocation invocation, Func<IInvocation, Task> proceed);
73+
protected abstract Task InterceptAsync(
74+
IInvocationProceedInfo proceedInfo,
75+
Func<IInvocationProceedInfo, Task> proceed);
7376

7477
/// <summary>
7578
/// Override in derived classes to intercept method invocations.
7679
/// </summary>
7780
/// <typeparam name="TResult">The type of the <see cref="Task{T}"/> <see cref="Task{T}.Result"/>.</typeparam>
78-
/// <param name="invocation">The method invocation.</param>
79-
/// <param name="proceed">The function to proceed the <paramref name="invocation"/>.</param>
81+
/// <param name="proceedInfo">The <see cref="IInvocationProceedInfo"/>.</param>
82+
/// <param name="proceed">The function to proceed the <paramref name="proceedInfo"/>.</param>
8083
/// <returns>A <see cref="Task" /> object that represents the asynchronous operation.</returns>
8184
protected abstract Task<TResult> InterceptAsync<TResult>(
82-
IInvocation invocation,
83-
Func<IInvocation, Task<TResult>> proceed);
85+
IInvocationProceedInfo proceedInfo,
86+
Func<IInvocationProceedInfo, Task<TResult>> proceed);
8487

8588
private static GenericSynchronousHandler CreateHandler(Type returnType)
8689
{
@@ -90,12 +93,15 @@ private static GenericSynchronousHandler CreateHandler(Type returnType)
9093

9194
private static void InterceptSynchronousVoid(AsyncInterceptorBase me, IInvocation invocation)
9295
{
93-
Task task = me.InterceptAsync(invocation, ProceedSynchronous);
96+
Task task = me.InterceptAsync(invocation.GetProceedInfo(), ProceedSynchronous);
9497

9598
// If the intercept task has yet to complete, wait for it.
9699
if (!task.IsCompleted)
97100
{
98-
Task.Run(() => task).Wait();
101+
// Need to use Task.Run() to prevent deadlock in .NET Framework ASP.NET requests.
102+
// GetAwaiter().GetResult() prevents a thrown exception being wrapped in a AggregateException.
103+
// See https://stackoverflow.com/a/17284612
104+
Task.Run(() => task).GetAwaiter().GetResult();
99105
}
100106

101107
if (task.IsFaulted)
@@ -106,12 +112,15 @@ private static void InterceptSynchronousVoid(AsyncInterceptorBase me, IInvocatio
106112

107113
private static void InterceptSynchronousResult<TResult>(AsyncInterceptorBase me, IInvocation invocation)
108114
{
109-
Task task = me.InterceptAsync(invocation, ProceedSynchronous<TResult>);
115+
Task<TResult> task = me.InterceptAsync(invocation.GetProceedInfo(), ProceedSynchronous<TResult>);
110116

111117
// If the intercept task has yet to complete, wait for it.
112118
if (!task.IsCompleted)
113119
{
114-
Task.Run(() => task).Wait();
120+
// Need to use Task.Run() to prevent deadlock in .NET Framework ASP.NET requests.
121+
// GetAwaiter().GetResult() prevents a thrown exception being wrapped in a AggregateException.
122+
// See https://stackoverflow.com/a/17284612
123+
Task.Run(() => task).GetAwaiter().GetResult();
115124
}
116125

117126
if (task.IsFaulted)
@@ -120,11 +129,11 @@ private static void InterceptSynchronousResult<TResult>(AsyncInterceptorBase me,
120129
}
121130
}
122131

123-
private static Task ProceedSynchronous(IInvocation invocation)
132+
private static Task ProceedSynchronous(IInvocationProceedInfo proceedInfo)
124133
{
125134
try
126135
{
127-
invocation.Proceed();
136+
proceedInfo.Invoke();
128137
#if NETSTANDARD2_0
129138
return Task.CompletedTask;
130139
#else
@@ -143,12 +152,12 @@ private static Task ProceedSynchronous(IInvocation invocation)
143152
}
144153
}
145154

146-
private static Task<TResult> ProceedSynchronous<TResult>(IInvocation invocation)
155+
private static Task<TResult> ProceedSynchronous<TResult>(IInvocationProceedInfo proceedInfo)
147156
{
148157
try
149158
{
150-
invocation.Proceed();
151-
return Task.FromResult((TResult)invocation.ReturnValue);
159+
proceedInfo.Invoke();
160+
return Task.FromResult((TResult)proceedInfo.Invocation.ReturnValue);
152161
}
153162
catch (Exception e)
154163
{
@@ -162,22 +171,22 @@ private static Task<TResult> ProceedSynchronous<TResult>(IInvocation invocation)
162171
}
163172
}
164173

165-
private static async Task ProceedAsynchronous(IInvocation invocation)
174+
private static async Task ProceedAsynchronous(IInvocationProceedInfo proceedInfo)
166175
{
167-
invocation.Proceed();
176+
proceedInfo.Invoke();
168177

169178
// Get the task to await.
170-
var originalReturnValue = (Task)invocation.ReturnValue;
179+
var originalReturnValue = (Task)proceedInfo.Invocation.ReturnValue;
171180

172181
await originalReturnValue.ConfigureAwait(false);
173182
}
174183

175-
private static async Task<TResult> ProceedAsynchronous<TResult>(IInvocation invocation)
184+
private static async Task<TResult> ProceedAsynchronous<TResult>(IInvocationProceedInfo proceedInfo)
176185
{
177-
invocation.Proceed();
186+
proceedInfo.Invoke();
178187

179188
// Get the task to await.
180-
var originalReturnValue = (Task<TResult>)invocation.ReturnValue;
189+
var originalReturnValue = (Task<TResult>)proceedInfo.Invocation.ReturnValue;
181190

182191
TResult result = await originalReturnValue.ConfigureAwait(false);
183192
return result;

test/Castle.Core.AsyncInterceptor.Tests/AsyncExceptionInterceptorShould.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,16 @@ public class WhenExceptionInterceptingAnAsynchronousMethodThatThrowsASynchronous
280280
{
281281
private class MyInterceptorBase : AsyncInterceptorBase
282282
{
283-
protected override Task InterceptAsync(IInvocation invocation, Func<IInvocation, Task> proceed)
283+
protected override Task InterceptAsync(IInvocationProceedInfo proceedInfo, Func<IInvocationProceedInfo, Task> proceed)
284284
{
285-
return proceed(invocation);
285+
return proceed(proceedInfo);
286286
}
287287

288-
protected override Task<TResult> InterceptAsync<TResult>(IInvocation invocation, Func<IInvocation, Task<TResult>> proceed)
288+
protected override Task<TResult> InterceptAsync<TResult>(
289+
IInvocationProceedInfo proceedInfo,
290+
Func<IInvocationProceedInfo, Task<TResult>> proceed)
289291
{
290-
return proceed(invocation);
292+
return proceed(proceedInfo);
291293
}
292294
}
293295

test/Castle.Core.AsyncInterceptor.Tests/InterfaceProxies/TestAsyncInterceptorBase.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,46 +18,46 @@ public TestAsyncInterceptorBase(ListLogger log, int msDeley)
1818
_msDeley = msDeley;
1919
}
2020

21-
protected override async Task InterceptAsync(IInvocation invocation, Func<IInvocation, Task> proceed)
21+
protected override async Task InterceptAsync(IInvocationProceedInfo proceedInfo, Func<IInvocationProceedInfo, Task> proceed)
2222
{
2323
try
2424
{
25-
_log.Add($"{invocation.Method.Name}:StartingVoidInvocation");
25+
_log.Add($"{proceedInfo.Invocation.Method.Name}:StartingVoidInvocation");
2626

2727
await Task.Yield();
28-
await proceed(invocation).ConfigureAwait(false);
28+
await proceed(proceedInfo).ConfigureAwait(false);
2929

3030
if (_msDeley > 0)
3131
await Task.Delay(_msDeley).ConfigureAwait(false);
3232

33-
_log.Add($"{invocation.Method.Name}:CompletedVoidInvocation");
33+
_log.Add($"{proceedInfo.Invocation.Method.Name}:CompletedVoidInvocation");
3434
}
3535
catch (Exception e)
3636
{
37-
_log.Add($"{invocation.Method.Name}:VoidExceptionThrown:{e.Message}");
37+
_log.Add($"{proceedInfo.Invocation.Method.Name}:VoidExceptionThrown:{e.Message}");
3838
throw;
3939
}
4040
}
4141

4242
protected override async Task<TResult> InterceptAsync<TResult>(
43-
IInvocation invocation,
44-
Func<IInvocation, Task<TResult>> proceed)
43+
IInvocationProceedInfo proceedInfo,
44+
Func<IInvocationProceedInfo, Task<TResult>> proceed)
4545
{
4646
try
4747
{
48-
_log.Add($"{invocation.Method.Name}:StartingResultInvocation");
48+
_log.Add($"{proceedInfo.Invocation.Method.Name}:StartingResultInvocation");
4949

50-
TResult result = await proceed(invocation).ConfigureAwait(false);
50+
TResult result = await proceed(proceedInfo).ConfigureAwait(false);
5151

5252
if (_msDeley > 0)
5353
await Task.Delay(_msDeley).ConfigureAwait(false);
5454

55-
_log.Add($"{invocation.Method.Name}:CompletedResultInvocation");
55+
_log.Add($"{proceedInfo.Invocation.Method.Name}:CompletedResultInvocation");
5656
return result;
5757
}
5858
catch (Exception e)
5959
{
60-
_log.Add($"{invocation.Method.Name}:ResultExceptionThrown:{e.Message}");
60+
_log.Add($"{proceedInfo.Invocation.Method.Name}:ResultExceptionThrown:{e.Message}");
6161
throw;
6262
}
6363
}

0 commit comments

Comments
 (0)