简体   繁体   English

通过反射调用方法而不会获得TargetInvocationException

[英]Invoke a method through reflection without getting TargetInvocationException

I've found a method using reflection (and got it's MethodInfo ). 我找到了一个使用反射的方法(并得到了它的MethodInfo )。 How can I invoke it without getting TargetInvocationException when exceptions are thrown? 抛出异常时,如何在不获取TargetInvocationException情况下调用它?

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 . 而不是必须捕获TargetInvocationException

(I know that I can throw the inner exception, but that's pretty worthless since the stack trace is destroyed) (我知道我可以抛出内部异常,但由于堆栈跟踪被破坏,这是非常没用的)

Update2 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. 创建一个DelegateMethodInfo (通过的重载之一Delegate.CreateDelegate )和调用该代替。 This won't wrap any exception thrown by the method inside a TargetInvocationException like MethodInfo.Invoke does. 不会将方法抛出的任何异常包装在类似MethodInfo.InvokeTargetInvocationException中。

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) (正如OP指出的那样,DynamicInvoke不会在这里工作,因为它也包装了)

Based on your update, I would just use dynamic : 根据您的更新,我会使用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. 如果希望效果是抛出的原始异常,则可以始终捕获TargetInvocationException ,然后抛出通过InnerException属性获取的“内部”异常。

(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.) (请注意,您将丢失原始堆栈跟踪。可能有一种方法可以防止这种情况,但这很棘手。我相信在.NET 4.5中可能会有更多支持;我不确定。)

You can call Invoke on the mehtodinfo instance, but the first argument of the call is the target (The object that the method info belongs to). 您可以在mehtodinfo实例上调用Invoke,但调用的第一个参数是目标(方法信息所属的对象)。 If you pass this and it has access to call it, you should not get the exception. 如果你通过它并且有权调用它,你就不应该得到例外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM