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);
        }