Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project updated to target .NET Standard 2.0 and async methods interception #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Added interception for async methods
Currently interception of async methods doesn't work as expected. Added Castle.Core.AsyncInterceptor and used IAsyncInterceptor in it to intercept async methods.
SachiraChin committed Apr 26, 2019
commit 0494b3101d5e97614e1c4cd05779ed42ad048640
112 changes: 99 additions & 13 deletions SimpleProxy/Internal/CoreInterceptor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
namespace SimpleProxy.Internal
using System.Collections.Generic;
using System.Threading.Tasks;
using SimpleProxy.Interfaces;

namespace SimpleProxy.Internal
{
using System;
using System.Linq;
@@ -9,7 +13,7 @@
/// <summary>
/// The Master Interceptor Class wraps a proxied object and handles all of its interceptions
/// </summary>
internal class CoreInterceptor : IInterceptor
internal class CoreInterceptor : IAsyncInterceptor
{
/// <summary>
/// Gets the <see cref="proxyConfiguration"/>
@@ -32,34 +36,116 @@ public CoreInterceptor(IServiceProvider serviceProvider, SimpleProxyConfiguratio
this.proxyConfiguration = proxyConfiguration;
}

/// <inheritdoc />
public void Intercept(IInvocation invocation)
public void InterceptSynchronous(IInvocation invocation)
{
// Map the configured interceptors to this type based on its attributes
var invocationMetadataCollection = InvocationExtensions.GetInterceptorMetadataForMethod(invocation, this.serviceProvider, this.proxyConfiguration);
var proceedWithInterception = InterceptBeforeProceed(invocation, out var invocationMetadataCollection, out var orderingStrategy);

// If there are no configured interceptors, leave now
if (invocationMetadataCollection == null || !invocationMetadataCollection.Any())
if (!proceedWithInterception)
{
invocation.Proceed();
return;
}

// Get the Ordering Strategy for Interceptors
var orderingStrategy = this.proxyConfiguration.OrderingStrategy;
// Execute the Real Method
if (!invocationMetadataCollection.Any(p => p.InvocationIsBypassed))
{
invocation.Proceed();
}

// Process the BEFORE Interceptions
foreach (var invocationContext in orderingStrategy.OrderBeforeInterception(invocationMetadataCollection))
InterceptAfterProceed(invocationMetadataCollection, orderingStrategy);
}

public void InterceptAsynchronous(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous(invocation);
}

private async Task InternalInterceptAsynchronous(IInvocation invocation)
{
var proceedWithInterception = InterceptBeforeProceed(invocation, out var invocationMetadataCollection, out var orderingStrategy);

if (!proceedWithInterception)
{
invocationContext.Interceptor.BeforeInvoke(invocationContext);
invocation.Proceed();
var task = (Task)invocation.ReturnValue;
await task;
return;
}

// Execute the Real Method
if (!invocationMetadataCollection.Any(p => p.InvocationIsBypassed))
{
invocation.Proceed();
var task = (Task)invocation.ReturnValue;
await task;
}

InterceptAfterProceed(invocationMetadataCollection, orderingStrategy);
}

public void InterceptAsynchronous<TResult>(IInvocation invocation)
{
invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation);
}

private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation)
{
var proceedWithInterception = InterceptBeforeProceed(invocation, out var invocationMetadataCollection, out var orderingStrategy);

TResult result;

if (!proceedWithInterception)
{
invocation.Proceed();
var task = (Task<TResult>)invocation.ReturnValue;
result = await task;
return result;
}

// Execute the Real Method
if (!invocationMetadataCollection.Any(p => p.InvocationIsBypassed))
{
invocation.Proceed();
var task = (Task<TResult>)invocation.ReturnValue;
result = await task;
}
else
{
result = default;
}

InterceptAfterProceed(invocationMetadataCollection, orderingStrategy);

return result;
}


private bool InterceptBeforeProceed(IInvocation invocation, out List<InvocationContext> invocationMetadataCollection, out IOrderingStrategy orderingStrategy)
{
// Map the configured interceptors to this type based on its attributes
invocationMetadataCollection = InvocationExtensions.GetInterceptorMetadataForMethod(invocation, this.serviceProvider, this.proxyConfiguration);

// If there are no configured interceptors, leave now
if (invocationMetadataCollection == null || !invocationMetadataCollection.Any())
{
orderingStrategy = null;
return false;
}

// Get the Ordering Strategy for Interceptors
orderingStrategy = this.proxyConfiguration.OrderingStrategy;

// Process the BEFORE Interceptions
foreach (var invocationContext in orderingStrategy.OrderBeforeInterception(invocationMetadataCollection))
{
invocationContext.Interceptor.BeforeInvoke(invocationContext);
}

return true;
}

private static void InterceptAfterProceed(List<InvocationContext> invocationMetadataCollection, IOrderingStrategy orderingStrategy)
{
// Process the AFTER Interceptions
foreach (var invocationContext in orderingStrategy.OrderAfterInterception(invocationMetadataCollection))
{
1 change: 1 addition & 0 deletions SimpleProxy/SimpleProxy.csproj
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Castle.Core" Version="4.3.1" />
<PackageReference Include="Castle.Core.AsyncInterceptor" Version="1.7.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />