Reputation: 1514
In our integration project we are dynamically delegating to a series of specific Processor objects using Reflection.
var genericType = typeof(IMessageProcessor<>).MakeGenericType(parseResponse.DomainMessage.GetType());
var miProcessMessage = genericType.GetMethod("ProcessMessage");
miProcessMessage.Invoke(processor, new object[] { parseResponse.DomainMessage });
Now, in certain situations, one of the processors needs to throw a specific Exception, in this case when he doesn't find a file in the expected location.
throw new ResourceNotFoundException(string.Format("Could not find file {0}", filePath));
Our processor wants to check on this exception to determine whether processing needs to be retried or aborted (based on a time-based mechanism, which is not relevant here).
catch(ResourceNotFoundException ex)
{
// do stuff
}
The problem is that the invoke apparently "swallows" the specific ResourceNotFoundException and rethrows a System.Exception saying "Exception has been thrown by the target of an invocation."
Is there any way of preserving the fact through Reflection that a ResourceNotFoundException was actually thrown and not an Exception?
Upvotes: 1
Views: 420
Reputation: 2721
MethodBase.Invoke(Object, Object[])
wraps any exception thrown by the invoked method in a TargetInvocationException
. You can access the inner exception and either process it directly, or rethrow it to be processed further up the stack as in the following example:
var genericType = typeof(IMessageProcessor<>).MakeGenericType(parseResponse.DomainMessage.GetType());
var miProcessMessage = genericType.GetMethod("ProcessMessage");
try {
miProcessMessage.Invoke(processor, new object[] { parseResponse.DomainMessage });
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
Note however that this will replace the inner exception's stack trace. A (technically unsupported) way of preserving the stack trace is described in this answer on SO.
Upvotes: 2