I have a call to MethodInfo.Invoke()
to execute a function through reflection. The call is wrapped in a try/catch
block but it still won't catch the exception thrown by the function I'm invoking.
I receive the following message:
Exception was unhandled by the user.
Why does MethodInfo.Invoke()
prevent the Exception to be caught outside of the Invoke()
?
How do I bypass it?
EDIT: As I understand your issue, the problem is purely an IDE one; you don't like VS treating the exception thrown by the invocation of the MethodInfo
as uncaught, when it clearly isn't. You can read about how to resolve this problem here: Why is TargetInvocationException treated as uncaught by the IDE? It appears to be a bug / by design; but one way or another, decent workarounds are listed in that answer.
As I see it, you have a couple of options:
You can use MethodInfo.Invoke
, catch the TargetInvocationException
and inspect its InnerException
property. You will have to workaround the IDE issues as mentioned in that answer.
You can create an appropriate Delegate
out of the MethodInfo
and invoke that instead. With this technique, the thrown exception will not be wrapped. Additionally, this approach does seem to play nicely with the debugger; I don't get any "Uncaught exception" pop-ups.
Here's an example that highlights both approaches:
class Program
{
static void Main()
{
DelegateApproach();
MethodInfoApproach();
}
static void DelegateApproach()
{
try
{
Action action = (Action)Delegate.CreateDelegate
(typeof(Action), GetMethodInfo());
action();
}
catch (NotImplementedException nie)
{
}
}
static void MethodInfoApproach()
{
try
{
GetMethodInfo().Invoke(null, new object[0]);
}
catch (TargetInvocationException tie)
{
if (tie.InnerException is NotImplementedException)
{
}
}
}
static MethodInfo GetMethodInfo()
{
return typeof(Program)
.GetMethod("TestMethod", BindingFlags.NonPublic | BindingFlags.Static);
}
static void TestMethod()
{
throw new NotImplementedException();
}
}
How are you trying to catch the exception? Typically what is thrown from a call to Invoke()
is a wrapping exception instance of System.Reflection.TargetInvocationException
. The actual exception you're after will be in the InnerException
.
try
{
method.Invoke(target, params);
}
catch (TargetInvocationException ex)
{
ex = ex.InnerException; // ex now stores the original exception
}