从保留动态调用方法例外 [英] Preserving exceptions from dynamically invoked methods

查看:186
本文介绍了从保留动态调用方法例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  • Related
  • Related

我要动态地调用 MethodInfo的对象,并有获得从里面向外传递就好像它是通常称为引发的任何异常。

I want to dynamically invoke a MethodInfo object and have any exceptions that get thrown from inside of it pass outward as if it were called normally.

我看来两个选项。他们概述如下。

I have two options it seems. They're outlined below.

选项1 维护着 MyStaticFunction ,而堆栈跟踪是因为

选项2 维护堆栈跟踪例外,但异常的类型总是 TargetInvocationException 。我可以拉出的InnerException 及其类型,但是这意味着我不能写,例如:

Option 2 maintains the StackTrace of the exception, but the type of the exception is always TargetInvocationException. I can pull out the InnerException and its type, but that means that I can't write this for example:

try { DoDynamicCall(); }
catch (MySpecialException e) { /* special handling */ }



选项​​1:

void DoDynamicCall()
{
    MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
    try
    {
        method.Invoke(null, new object[] { 5 });
    }
    catch (TargetInvocationException e)
    {
        throw e.InnerException;
    }
}

选项2:

void DoDynamicCall()
{
    MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
    method.Invoke(null, new object[] { 5 });
}



我真正想要是主叫方 DoDynamicCall 接收例外,如果有人叫这样的:

What I really want is for callers to DoDynamicCall to receive exceptions as if they had called this:

void DoDynamicCall()
{
    MyClass.MyStaticFunction(5);
}



有没有办法让这两个选项1 <的好处/ strong>和选项2

选择我希望我有(发明了特殊的新C#的关键字重新抛出现场):

The option I wish I had (invented special new C# keyword rethrow on the spot):

void DoDynamicCall()
{
    MethodInfo method = /*referencing MyClass method void MyStaticFunction(int x)*/;
    try
    {
        method.Invoke(null, new object[] { 5 });
    }
    catch (TargetInvocationException e)
    {
        //Magic "rethrow" keyword passes this exception
        //onward unchanged, rather than "throw" which
        //modifies the StackTrace, among other things
        rethrow e.InnerException;
    }
}

这也将消除这种怪人的需要,因为你可以使用重新抛出ë; 而不是:

This would also eliminate the need for this weirdo, because you could use rethrow e; instead:

try { ... }
catch (Exception e)
{
    if (...)
        throw;
}

在一般情况下,这将是一个方法去耦扔; 从需求。我直接在catch块是

In general, it would be a way to decouple throw; from the requirement "I have to be directly in a catch block."

推荐答案

下面是该解决方案我想出了。它能够完成任务。我仍然有兴趣在其他的答案,因为可能有一些简单或清洁剂。

Here's the solution I came up with. It gets the job done. I'm still interested in other answers as there might be something easier or cleaner.


  • 当您想要的功能扔; ,但你想传递的例外是不是当前块,使用外扔功能.Rethrow(E);

  • 替换的try ... catch ... Functional.TryCatch

  • 替换的try ... catch ...终于... Functional.TryCatchFinally

  • When you want the functionality of throw; but the exception you want to pass on is not the exception of the current catch block, use throw Functional.Rethrow(e);
  • Replace try...catch... with Functional.TryCatch
  • Replace try...catch...finally... with Functional.TryCatchFinally

下面的代码:

//Need a dummy type that is throwable and can hold an Exception
public sealed class RethrowException : Exception
{
    public RethrowException(Exception inner) : base(null, inner) { }
}

public static Functional
{    
    public static Exception Rethrow(Exception e)
    {
        return new RethrowException(e);
    }

    public static void TryCatch(Action _try, Action<Exception> _catch)
    {
        try { _try(); }
        catch (RethrowException e) { _catch(e.InnerException); }
        catch (Exception e) { _catch(e); }
    }

    public static T TryCatch<T>(Func<T> _try, Func<Exception, T> _catch)
    {
        try { return _try(); }
        catch (RethrowException e) { return _catch(e.InnerException); }
        catch (Exception e) { return _catch(e); }
    }

    public static void TryCatchFinally(
        Action _try, Action<Exception> _catch, Action _finally)
    {
        try { _try(); }
        catch (RethrowException e) { _catch(e.InnerException); }
        catch (Exception e) { _catch(e); }
        finally { _finally(); }
    }

    public static T TryCatchFinally<T>(
        Func<T> _try, Func<Exception, T> _catch, Action _finally)
    {
        try { return _try(); }
        catch (RethrowException e) { return _catch(e.InnerException); }
        catch (Exception e) { return _catch(e); }
        finally { _finally(); }
    }
}



更新



在.NET 4.5有新的 System.Runtime.ExceptionServices.ExceptionDispatchInfo 。这可以用来捕获异常:

Update

In .NET 4.5 there is the new System.Runtime.ExceptionServices.ExceptionDispatchInfo class. This can be used to capture an exception:

var capturedException = ExceptionDispatchInfo.Capture(e);



再后来这被用于恢复抛出异常:

And then later this is used to resume throwing the exception:

capturedException.Throw();

这篇关于从保留动态调用方法例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆