我找到了一种使用反射的方法(并且得到了它MethodInfo
)。如果抛出异常,如何在不获取TargetInvocationException
的情况下调用它?
更新
我正在创建一个命令实现,其中命令由实现
的类处理public interface ICommandHandler<T> where T : class, ICommand
{
public void Invoke(T command);
}
由于有一个调度程序负责查找并将所有处理程序映射到正确的命令,因此我不能直接调用这些方法,而是使用反射。类似的东西:
var handlerType = tyepof(IHandlerOf<>).MakeGenericType(command.GetType());
var method = handlerType.GetMethod("Invoke", new [] { command.GetType() });
method.Invoke(theHandler, new object[]{command});
它运行正常,但我希望将所有异常传递给调用该命令的代码。
这样调用者就可以使用:
try
{
_dispatcher.Invoke(new CreateUser("Jonas", "Gauffin"));
}
catch (SomeSpecificException err)
{
//handle it.
}
而不是必须抓住TargetInvocationException
。
(我知道我可以抛出内部异常,但由于堆栈跟踪被破坏,这非常没用)
UPDATE2
Here是一种可能的解决方案..
但它似乎更像是一个黑客。 Aren有更好的解决方案吗?也许用表情或什么?
答案 0 :(得分:5)
从Delegate
(通过Delegate.CreateDelegate
的重载之一)创建MethodInfo
并调用它。这个不会包装方法抛出的TargetInvocationException
MethodInfo.Invoke
内的任何异常。
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);
}
}
修改强>:
(正如OP指出的那样,DynamicInvoke在这里不会起作用,因为它也包装了)
根据您的更新,我只会使用dynamic
:
((dynamic)theHandler).Invoke(command);
答案 1 :(得分:3)
你做不到。这是通过反射调用方法传播异常的指定方式。您可以随时捕获TargetInvocationException
,然后抛出通过InnerException
属性获得的“内部”异常,如果您希望效果是抛出的原始异常。
(你会失去原有的堆栈跟踪,请注意。有可能有一种方法可以防止这种情况,但这很棘手。我相信可能可以在.NET 4.5中为此提供更多支持;我不确定。)
答案 2 :(得分:-1)
您可以在mehtodinfo实例上调用Invoke,但调用的第一个参数是目标(方法信息所属的对象)。如果你通过它并且有权调用它,你就不应该得到例外。