从保留动态调用方法例外 [英] Preserving exceptions from dynamically invoked methods
问题描述
- 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 $ C $抛出的异常的类型C>,而
堆栈跟踪
是因为扔
。
选项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 currentcatch
block, usethrow Functional.Rethrow(e);
- Replace
try...catch...
withFunctional.TryCatch
- Replace
try...catch...finally...
withFunctional.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屋!