I have a generic class that catches exceptions of T:
public abstract class ErrorHandlingOperationInterceptor<T> : OperationInterceptor where T : ApiException { private readonly Func<OperationResult> _resultFactory; protected ErrorHandlingOperationInterceptor(Func<OperationResult> resultFactory) { _resultFactory = resultFactory; } public override Func<IEnumerable<OutputMember>> RewriteOperation(Func<IEnumerable<OutputMember>> operationBuilder) { return () => { try { return operationBuilder(); } catch (T ex) { var operationResult = _resultFactory(); operationResult.ResponseResource = new ApiErrorResource { Exception = ex }; return operationResult.AsOutput(); } }; } }
With subclasses for specific exceptions e.g.
public class BadRequestOperationInterceptor : ErrorHandlingOperationInterceptor<BadRequestException> { public BadRequestOperationInterceptor() : base(() => new OperationResult.BadRequest()) { } }
This all seems to work perfectly. But, somehow, in the logs (once, not every time) is an InvalidCastException:
System.InvalidCastException: Unable to cast object of type 'ErrorHandling.Exceptions.ApiException' to type 'ErrorHandling.Exceptions.UnexpectedInternalServerErrorException'. at OperationModel.Interceptors.ErrorHandlingOperationInterceptor`1.c__DisplayClass2.b__1() in c:\BuildAgent\work\da77ba20595a9d4\src\OperationModel\Interceptors\ErrorHandlingOperationInterceptor.cs:line 28
Line 28 is the catch.
What am I missing? Have I done something really dumb?
1) Following is a simple example to show exception handling in C++. The output of program explains flow of execution of try/catch blocks. 2) There is a special catch block called ‘catch all’ catch (…) that can be used to catch all types of exceptions.
This is because some exceptions are not exceptions in a C++ context. This includes things like division by zero errors and others. It is possible to hack about and thus get the ability to throw exceptions when these errors happen, but it's not easy to do and certainly not easy to get right in a portable manner.
And either the exception happens or it doesn't. If it doesn't happen, catching the exception makes no difference but is a waste of effort. If it happens and nobody knows how to handle it and you catch it, there's no benefit coming from that - the only benefit would come from someone figuring out how to handle it.
Throwing an exception with no catch block to handle it is when this exception occurs. The .NET Framework provides an easy mechanism to subscribe to every exception thrown in your code. This includes exceptions that are caught deep inside your code that never get surfaced anywhere.
As smithy said, your T
is of type ApiErrorResource
. You are, some where in your code, attempting to create your ErrorHandlingOperationInterceptor
with an Exception
that is NOT derived from ApiErrorResource
.
try
{
// throw Exception of some sort
}
catch (BadRequestException ex)
{
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}
catch (Exception ex)
{
// this is NOT right
BadRequestOperationInterceptor broi = new BadRequestOperationInterceptor ();
}
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