I am starting to work with ninject interceptors to wrap some of my async code with various behaviors and am having some trouble getting everything working.
Here is an interceptor I am working with:
public class MyInterceptor : IInterceptor
{
public async void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
//check that method indeed returns Task
await (Task) invocation.ReturnValue;
RecordSuccess();
}
catch (Exception)
{
RecordError();
invocation.ReturnValue = _defaultValue;
throw;
}
}
This appears to run properly in most normal cases. I am not sure if this will do what I expect. Although it appears to return control flow to the caller asynchronously, I am still a bit worried about the possibility that the proxy is unintentionally blocking a thread or something.
That aside, I cannot get the exception handling working. For this test case:
[Test]
public void ExceptionThrown()
{
try
{
var interceptor = new MyInterceptor(DefaultValue);
var invocation = new Mock<IInvocation>();
invocation.Setup(x => x.Proceed()).Throws<InvalidOperationException>();
interceptor.Intercept(invocation.Object);
}
catch (Exception e)
{
}
}
I can see in the interceptor that the catch block is hit, but the catch block in my test is never hit from the rethrow. I am more confused because there is no proxy or anything here, just pretty simple mocks and objects. I also tried something like Task.Run(() => interceptor.Intercept(invocation.Object)).Wait();
in my test, and still no change. The test passes happily, but the nUnit output does have the exception message.
I imagine I am messing something up, and I don't quite understand what is going on as much as I think I do. Is there a better way to intercept an async method? What am I doing wrong with regards to exception handling?
IInterceptor.Intercept
method is void. I can make it async, but maybe I am not properly waiting for it in the test or something. That doesn't make sense to me though, because in this path nothing asynchronous has even happened yet. – Tesslerasync void
method are almost always a bad idea, unless you're writing an event handler. And I think to do this, Ninject would have to supportasync
. – Kilbride