I've found a method using reflection (and got it's MethodInfo
). How can I invoke it without getting TargetInvocationException
when exceptions are thrown?
Update
I'm creating a command implementation where the commands are handled by classes which implemement
public interface ICommandHandler<T> where T : class, ICommand
{
public void Invoke(T command);
}
Since there is one dispatcher which takes care of find and map all handlers to the correct command I can't invoke the methods directly but by using reflection. Something like:
var handlerType = tyepof(IHandlerOf<>).MakeGenericType(command.GetType());
var method = handlerType.GetMethod("Invoke", new [] { command.GetType() });
method.Invoke(theHandler, new object[]{command});
It works fine, but I want all exceptions to get passed on to the code that invoked the command.
So that the caller can use:
try
{
_dispatcher.Invoke(new CreateUser("Jonas", "Gauffin"));
}
catch (SomeSpecificException err)
{
//handle it.
}
Instead of having to catch TargetInvocationException
.
(I know that I can throw the inner exception, but that's pretty worthless since the stack trace is destroyed)
Update2
Here is a possible solution..
But it seems more like a hack. Aren't there a better solution? Maybe with expressions or something?
Create a Delegate
from the MethodInfo
(through one of the overloads of Delegate.CreateDelegate
) and invoke that instead. This won't wrap any exception thrown by the method inside a TargetInvocationException
like MethodInfo.Invoke
does.
class Foo
{
static void ThrowingMethod()
{
throw new NotImplementedException();
}
static MethodInfo GetMethodInfo()
{
return typeof(Foo)
.GetMethod("ThrowingMethod", BindingFlags.NonPublic | BindingFlags.Static);
}
// Will throw a NotImplementedException
static void DelegateWay()
{
Action action = (Action)Delegate.CreateDelegate
(typeof(Action), GetMethodInfo());
action();
}
// Will throw a TargetInvocationException
// wrapping a NotImplementedException
static void MethodInfoWay()
{
GetMethodInfo().Invoke(null, null);
}
}
EDIT:
(As the OP has pointed out, DynamicInvoke won't work here since it wraps too)
Based on your update, I would just use dynamic
:
((dynamic)theHandler).Invoke(command);
You can't. That's the specified way that exceptions are propagated by invoking a method via reflection. You can always catch TargetInvocationException
and then throw the "inner" exception obtained via the InnerException
property, if you want the effect to be the original exception being thrown.
(You'll lose the original stack trace, mind you. It's possible that there's a way to prevent that, but it's tricky. I believe there may be more support for this in .NET 4.5; I'm not sure.)
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