unitycontainer / interception

Unity.Interception package
Apache License 2.0
22 stars 17 forks source link

Async method support in IInterceptionBehaviour #16

Open wilversings opened 6 years ago

wilversings commented 6 years ago

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.

ENikS commented 6 years ago

Unity as of now does not do anything asynchronously. Can you provide more info?

wilversings commented 6 years ago

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 commented 6 years ago

Please do

wilversings commented 6 years ago
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.

ENikS commented 6 years ago

You are not alone in this thought. The support for async is in preliminary stages of development

ArnaudB88 commented 6 years ago

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

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 commented 5 years ago

Hi, what's the progress of this feature? Thx!

ENikS commented 5 years ago

Still in development

kajbonfils commented 4 years ago

Can you provide a new status? Still in dev? Any ideas on when to expect this to be ready?

ENikS commented 4 years ago

The optimistic prognosis would be sometime in September