Using unity interception to solve exception handling as a crosscutting concern
Я создал свое собственное поведение следующим образом:
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; }
}
}
У меня настроено правильно, так что мое поведение получает удар, как и ожидалось. Однако, если какое-либо исключение происходит в том, что делает getNext(), оно не попадает в мой блок catch. Кто-нибудь может уточнить почему? Я на самом деле не пытаюсь решить эту проблему, так как есть много способов справиться с исключениями, скорее, я не понимаю, что происходит, и мне бы хотелось.
3 ответа
Вы не можете поймать какое-либо исключение, если возникнет исключение, оно будет частью свойства Exception объекта IMethodReturn.
Вот так:
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;
}
Я знаю, что это старый пост, но решение гедеона выдаетисключение нулевой ссылки Unity. И я хочу обработать Исключение в вызывающей стороне, а не в Перехвате Единства.
Вот рабочее решение, которое выбрасывает исключение на вызывающего, а не на перехват:
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;
}
Затем, когда вы вызываете свой перехваченный метод, вы можете получить исключение:
try
{
// Method intercepted by Unity pipeline
InterceptedMethod();
}
catch(Exception e)
{
//Exception handling
}
Я думаю, что есть еще один важный момент. Исключение не будет обработано и сохранено в IMethodReturn.Exception
если он был брошен глубже в конвейер поведения. Потому что Unity создает перехваченный метод-обертку, который InvokeInterceptionBehaviorDelegate
Например, окружая вызов метода с try-catch
блок. Но это не относится к вашему методу перехватчика. Вы можете проверить метод CreateDelegateImplementation() и класс InterceptionBehaviorPipeline, чтобы получить более подробную информацию о том, как это делается.
Если вы хотите обрабатывать исключения, которые были сгенерированы другими, более глубокими перехватчиками, вы можете использовать что-то вроде этого:
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;
}