6

我找到了一种使用反射的方法(并且得到了它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

(我知道我可以抛出内部异常,但由于堆栈跟踪已被破坏,这毫无价值)

更新2

是一个可能的解决方案..

但它似乎更像是一个黑客。没有更好的解决方案吗?也许是用表情之类的?

4

3 回答 3

5

DelegateMethodInfo(通过 的重载之一)创建一个Delegate.CreateDelegate并调用它。这不会将方法抛出的任何异常包装在TargetInvocationExceptionlikeMethodInfo.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);
于 2012-06-21T14:11:10.813 回答
3

你不能。这是通过反射调用方法来传播异常的指定方式。如果您希望效果是被抛出的原始异常,您总是可以捕获TargetInvocationException然后抛出通过属性获得的“内部”异常。InnerException

(请注意,您将丢失原始堆栈跟踪。可能有一种方法可以防止这种情况发生,但这很棘手。我相信.NET 4.5 中可能会对此提供更多支持;我不确定。)

于 2012-06-21T14:10:38.893 回答
-1

您可以在 mehtodinfo 实例上调用 Invoke,但调用的第一个参数是目标(方法信息所属的对象)。如果你通过它并且它有权调用它,你不应该得到异常。

于 2012-06-21T14:10:31.837 回答