public object HandleCall(Type reflectedType, string methodName, object[] arguments, Type[] argumentTypes, Type resultType) { bool adaptedExceptionBeforeCall = false; bool adaptedExceptionDuringCall = false; bool adaptedExceptionAfterCall = false; Exception previousThrownException = null; // Construct the Call Info var callInfo = new CallInfo(reflectedType, methodName, arguments, argumentTypes, resultType); // Let the intercepter know that the call is being performed if (_interceptor != null) { try { _interceptor.BeforeCall(callInfo); } catch (Exception e) { var message = string.Format( "While intercepting a call to '{0}', the BeforeCall method of '{1}' threw an exception of type '{2}' with the following message:\r\n{3}", methodName, _interceptor.GetType().FullName, e.GetType().FullName, e.Message); throw new InterceptionException(message, e, methodName, arguments, true, false); } } // Check if the interceptor wants the call to throw an exception, // store it as an AdaptedException thrown during BeforeCall if (callInfo.Completed && callInfo.ThrownException != null) { adaptedExceptionBeforeCall = true; previousThrownException = callInfo.ThrownException; } // Perform the actual call to the adapted object. The // PerformAdaptedCall method should catch any exceptions // thrown from the adapted, and put it in the callInfo. // Only perform the adapted call if the BeforeCall of the // interceptor haven't marked the call as Completed. if (!callInfo.Completed) { PerformAdaptedCall(callInfo); if (callInfo.Completed && callInfo.ThrownException != null) { adaptedExceptionDuringCall = true; previousThrownException = callInfo.ThrownException; } } // Inform the interceptor that the method call in finished if (_interceptor != null) { try { _interceptor.AfterCall(callInfo); } catch (Exception e) { var message = string.Format( "While intercepting a call to '{0}', the AfterCall method of '{1}' threw an exception of type '{2}' with the following message:\r\n{3}", methodName, _interceptor.GetType().FullName, e.GetType().FullName, e.Message); throw new InterceptionException(message, e, methodName, arguments, false, true); } } // Check if the AfterCall has marked a ThrownException of its own if (callInfo.ThrownException != null) { if (callInfo.ThrownException != previousThrownException) { adaptedExceptionAfterCall = true; } } // Decide if the method call should finally throw an exception, // or just return the intended value. if (callInfo.ThrownException != null) { var interceptorName = (_interceptor == null) ? "Null" : _interceptor. GetType().FullName; var adaptedName = (_adapted == null) ? "Null" : _adapted.GetType().FullName; var message = string.Format( "While adapting a call to '{0}' with interceptor '{1}' and adapted type '{2}', an exception of type '{3}' is thrown, with the following message:\r\n{4}", methodName, interceptorName, adaptedName, callInfo.ThrownException.GetType().FullName, callInfo.ThrownException.Message); throw new AdaptedException(message, callInfo.ThrownException, methodName, arguments, adaptedExceptionBeforeCall, adaptedExceptionDuringCall, adaptedExceptionAfterCall); } return(callInfo.ReturnValue); }