/// <summary>
        ///   Asserts that the thrown exception has a message that matches <paramref name = "expectedMessage" />
        ///   depending on the specified matching mode.
        /// </summary>
        /// <param name = "expectedMessage">
        ///   The expected message of the exception.
        /// </param>
        /// <param name = "comparisonMode">
        ///   Determines how the expected message is compared with the actual message.
        /// </param>
        /// <param name = "reason">
        ///   A formatted phrase as is supported by <see cref = "string.Format(string,object[])" /> explaining why the assertion
        ///   is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
        /// </param>
        /// <param name = "reasonArgs">
        ///   Zero or more objects to format using the placeholders in <see cref = "reason" />.
        /// </param>
        public virtual ExceptionAssertions <TException> WithMessage(string expectedMessage, ComparisonMode comparisonMode,
                                                                    string reason = "", params object[] reasonArgs)
        {
            AssertionScope assertion = Execute.Assertion.BecauseOf(reason, reasonArgs).UsingLineBreaks;

            assertion
            .ForCondition(Subject.Any())
            .FailWith("Expected exception with message {0}{reason}, but no exception was thrown.", expectedMessage);

            ExceptionMessageAssertion messageAssertion = outerMessageAssertions[comparisonMode];

            messageAssertion.Execute(Subject.Select(exc => exc.Message).ToArray(), expectedMessage, reason, reasonArgs);

            return(this);
        }
        /// <summary>
        ///   Asserts that the thrown exception contains an inner exception with the <paramref name = "expectedInnerMessage" />.
        /// </summary>
        /// <param name = "expectedInnerMessage">The expected message of the inner exception.</param>
        /// <param name = "comparisonMode">Determines how the expected message is compared with the actual message.</param>
        /// <param name = "reason">
        ///   The reason why the message of the inner exception should match <paramref name = "expectedInnerMessage" />.
        /// </param>
        /// <param name = "reasonArgs">The parameters used when formatting the <paramref name = "reason" />.</param>
        public virtual ExceptionAssertions <TException> WithInnerMessage(string expectedInnerMessage,
                                                                         ComparisonMode comparisonMode, string reason, params object[] reasonArgs)
        {
            AssertionScope assertion = Execute.Assertion
                                       .BecauseOf(reason, reasonArgs)
                                       .UsingLineBreaks;

            assertion
            .ForCondition(Subject.Any())
            .FailWith("Expected inner exception{reason}, but no exception was thrown.");

            assertion
            .ForCondition(Subject.Any(e => e.InnerException != null))
            .FailWith("Expected inner exception{reason}, but the thrown exception has no inner exception.");

            string[] subjectInnerMessage = Subject.Select(e => e.InnerException.Message).ToArray();

            ExceptionMessageAssertion messageAssertion = innerMessageAssertions[comparisonMode];

            messageAssertion.Execute(subjectInnerMessage, expectedInnerMessage, reason, reasonArgs);

            return(this);
        }