You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Async method support in IInterceptionBehaviour #16
My usecase is that I'm trying to implement entry/exit/exception logging on an async method.
I an IInterceptionBehavoiur implementation, the call to getNext()(...) is performed asynchronously and I don't get to log the exit of the funciton.
In case of an awaitable target of the interception, I should be able to await the result in the IInterceptionBehavior.Invoke. Should I provide a more elaborate example?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Unity;
using Unity.Interception.ContainerIntegration;
using Unity.Interception.InterceptionBehaviors;
using Unity.Interception.Interceptors.InstanceInterceptors.InterfaceInterception;
using Unity.Interception.PolicyInjection.Pipeline;
namespace Program
{
public class Program
{
public static void Main(string[] args)
{
IUnityContainer container = new UnityContainer().AddNewExtension<Interception>();
container.RegisterType<IInterface, ConcreteClass>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<InterceptBehavior>());
var myInterface = container.Resolve<IInterface>();
myInterface.Method().Wait();
}
}
public interface IInterface
{
Task Method();
}
public class ConcreteClass : IInterface
{
public async Task Method()
{
await Task.Delay(1000);
Console.WriteLine("Method Called");
await Task.Delay(1000);
}
}
public class InterceptBehavior : IInterceptionBehavior
{
public bool WillExecute => true;
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("Before the call");
var result = getNext()(input, getNext);
Console.WriteLine("After the call");
return result;
}
}
}
The output of this will be
Before the call
After the call
Method called
Because ConcreteClass's Method is async, and currently there is no way to await the result in the InterceptBehavior's Invoke method.
Even though I can work around that, with:
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Console.WriteLine("Before the call");
var result = getNext()(input, getNext);
if (result.ReturnValue is Task res)
{
result.ReturnValue = res.ContinueWith(_ => Console.WriteLine("After the call"));
}
else
{
Console.WriteLine("After the call");
}
return result;
}
it still feels like the async targets could be supported by the library.
One option to implement default support for async interception is a separate interceptor for sync and async method calls. The existing code can remain, and a new 'IAsyncInterceptionBehaviour' oid can be added. Core unity logic should choose the correct interceptor based on the method's type.
Minor disadvantage: registering an interface with both async and sync methods would then have two interceptionBehaviours.
An example of this can be found in the structureMap library: http://structuremap.github.io/dynamic-interception/
Other option is expanding the current InterceptionBehaviour with an extra InvokeAsync() method. Minor disadvantage: that will force the users to change their existing implementations (adding impl. for the async method).
Advantage: registering an interface with both async and sync method will not change.
Edit:
Note on the code download: remove the 'configureAwait(false)' from the code, because that will lose the httpContext. If some logging is done afterwards which uses the DI container for eg. logging the username of the current user, and the DI container uses the HttpContext, an error occurs.
Activity
ENikS commentedon Jun 21, 2018
Unity as of now does not do anything asynchronously. Can you provide more info?
wilversings commentedon Jun 21, 2018
In case of an awaitable target of the interception, I should be able to await the result in the IInterceptionBehavior.Invoke. Should I provide a more elaborate example?
ENikS commentedon Jun 21, 2018
Please do
wilversings commentedon Jun 21, 2018
The output of this will be
Because
ConcreteClass'sMethodis async, and currently there is no way to await theresultin theInterceptBehavior'sInvokemethod.Even though I can work around that, with:
it still feels like the async targets could be supported by the library.
ENikS commentedon Jun 21, 2018
You are not alone in this thought.
The support for async is in preliminary stages of development
ArnaudB88 commentedon Jun 27, 2018
More information on how it can be handled at the moment:
https://msdn.microsoft.com/en-us/magazine/dn574805.aspx
Code download:
https://msdn.microsoft.com/magazine/msdnmag0214
One option to implement default support for async interception is a separate interceptor for sync and async method calls. The existing code can remain, and a new 'IAsyncInterceptionBehaviour' oid can be added. Core unity logic should choose the correct interceptor based on the method's type.
Minor disadvantage: registering an interface with both async and sync methods would then have two interceptionBehaviours.
An example of this can be found in the structureMap library:
http://structuremap.github.io/dynamic-interception/
Other option is expanding the current InterceptionBehaviour with an extra InvokeAsync() method. Minor disadvantage: that will force the users to change their existing implementations (adding impl. for the async method).
Advantage: registering an interface with both async and sync method will not change.
Edit:
Note on the code download: remove the 'configureAwait(false)' from the code, because that will lose the httpContext. If some logging is done afterwards which uses the DI container for eg. logging the username of the current user, and the DI container uses the HttpContext, an error occurs.
ArnaudB88 commentedon Oct 18, 2018
Hi, what's the progress of this feature?
Thx!
ENikS commentedon Oct 23, 2018
Still in development
kajbonfils commentedon Aug 15, 2019
Can you provide a new status? Still in dev? Any ideas on when to expect this to be ready?
ENikS commentedon Aug 21, 2019
The optimistic prognosis would be sometime in September