I created my own behavior as follows:
public class BoundaryExceptionHandlingBehavior : IInterceptionBehavior
{
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
try
{
return getNext()(input, getNext);
}
catch (Exception ex)
{
return null; //this would be something else...
}
}
public bool WillExecute
{
get { return true; }
}
}
I have it setup correctly so that my behavior gets hit as expected. However, if any exception happens in whatever getNext() does, it doesn't hit my catch block. Can anyone clarify why? I'm not really looking to solve the problem as there's many ways to deal with exceptions, it's more that I don't understand what's going on, and I'd like to.
You can't catch any exception, if an Exception occurs it will be part of the Exception property of IMethodReturn.
Like so:
public IMethodReturn Invoke(IMethodInvocation input,
GetNextInterceptionBehaviorDelegate getNext)
{
IMethodReturn ret = getNext()(input, getNext);
if(ret.Exception != null)
{//the method you intercepted caused an exception
//check if it is really a method
if (input.MethodBase.MemberType == MemberTypes.Method)
{
MethodInfo method = (MethodInfo)input.MethodBase;
if (method.ReturnType == typeof(void))
{//you should only return null if the method you intercept returns void
return null;
}
//if the method is supposed to return a value type (like int)
//returning null causes an exception
}
}
return ret;
}
I think there is one more important point to make. Exception will not be handled and saved to IMethodReturn.Exception
if it was thrown deeper within behaviors pipeline. Because Unity creates intercepted method wrapper, which is InvokeInterceptionBehaviorDelegate
instance, by surrounding method invocation with try-catch
block. But that is not the case for your interceptor method. You can check CreateDelegateImplementation() method and InterceptionBehaviorPipeline class to get more details about how this is done.
If you want to process exceptions that were thrown from other, deeper interceptors too you can use something like this:
public IMethodReturn Invoke(IMethodInvocation input,
GetNextInterceptionBehaviorDelegate getNext)
{
try
{
return InvokeImpl(input, getNext);
}
catch (Exception exception)
{
// Process exception and return result
}
}
private IMethodReturn InvokeImpl(IMethodInvocation input,
GetNextInterceptionBehaviorDelegate getNext)
{
var methodReturn = getNext().Invoke(input, getNext);
if (methodReturn.Exception != null)
// Process exception and return result
return methodReturn;
}
I know it is an old post but the gideon's solution throw an Unity null reference Exception. And i want to handle the Exception in the caller and not in the Unity Interception.
Here is a working solution that throw the Exception on the caller and not into the Interception:
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
IMethodReturn ret = getNext()(input, getNext);
if (ret.Exception != null)
{
// Throw the Exception out of the Unity Interception
ExceptionDispatchInfo.Capture(ret.Exception).Throw();
}
// Process return result
return ret;
}
Then when you call your intercepted method you can get the Exception:
try
{
// Method intercepted by Unity pipeline
InterceptedMethod();
}
catch(Exception e)
{
//Exception handling
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With