保持动态调用方法的异常我想动态调用一个MethodInfo对象,从里面抛出任何异常再传递出去,就像正常调用一样。在我看来,有两种选择。它们概述如下。选项1维护MyStaticFunction抛出的异常类型,但StackTrace因抛出而中断。选项2维护异常的StackTrace,但异常的类型始终是TargetInvocationException。我可以提取InnerException及其类型,但这意味着我无法编写示例:try{DoDynamicCall();}catch(MySpecialExceptione){/*特殊处理*/}选项1:voidDoDynamicCall(){MethodInfomethod=/*referencingMyClassmethodvoidMyStaticFunction(intx)*/;try{method.Invoke(null,newobject[]{5});}catch(TargetInvocationExceptione){throwe.InnerException;}}选项2:voidDoDynamicCall(){MethodInfomethod=/*referencingMyClassmethodvoidMyStaticFunction(intx)*/;method.Invoke(null,newobject[]{5});我真正想要的是让DoDynamicCall调用者接收异常,就好像他们已经调用了这个:voidDoDynamicCall(){MyClass.MyStaticFunction(5);有没有办法获得选项1和选项2的好处?编辑:我希望我有的选项(当场发明的特殊新C#关键字rethrow):try{method.Invoke(null,newobject[]{5});}catch(TargetInvocationExceptione){//神奇的“rethrow”关键字传递此异常//向前不变,而不是“抛出”哪个//修改StackTrace,除此之外重新抛出e.InnerException;这也消除了对这个怪人的需要,因为你可以使用rethrowe;相反:try{...}catch(Exceptione){if(...)throw;通常,这是一种解耦throw的方法;从要求“我必须直接进入阻塞块”这是我想出的解决方案。它完成了工作。我仍然对其他答案感兴趣,因为可能会有更简单或更清洁的东西。这是代码://需要一个可抛出的虚拟类型并且可以持有一个异常异常e){返回新的RethrowException(e);}publicstaticvoidTryCatch(Action_try,Action_catch){try{_try();}catch(RethrowExceptione){_catch(e.InnerException);}赶上(异常e){_catch(e);}}publicstaticTTryCatch(Func_try,Func_catch){try{return_try();}catch(RethrowExceptione){return_catch(e.InnerException);}catch(Exceptione){return_catch(e);}}publicstaticvoidTryCatchFinally(Action_try,Action_catch,Action_finally){try{_try();}catch(RethrowExceptione){_catch(e.InnerException);}赶上(异常e){_catch(e);}最后{_finally();}}publicstaticTTryCatchFinally(Func_try,Func_catch,Action_finally){try{return_try();}catch(RethrowExceptione){return_catch(e.InnerException);}catch(Exceptione){return_catch(e);}最后{_finally();}}}更新在.NET4.5中,有新的System.Runtime.ExceptionServices.ExceptionDispatchInfo类这可以用来捕获异常:varcapturedException=ExceptionDispatchInfo.Capture(e);然后这用于恢复抛出的异常:capturedException.Throw();不,我不相信有办法让两者都很好。但是,抛出e.InnerException仍然可以让您获得原始堆栈跟踪,因为您只是使用e.InnerException.StackTrace来获取原始堆栈跟踪。因此,简而言之,您应该使用选项1。最好的选择是选项3:根本不使用反射,而是使用Expression.Compile()。而不是这样做:staticvoidCallMethodWithReflection(MethodInfomethod){try{method.Invoke(null,newobject[0]);}catch(TargetInvocationExceptionexp){throwexp.InnerException;}}尝试针对此:privatestaticvoidCallMethodWithExpressionCompile(MethodInfomethod){Expression.Lambda(Expression.Call(method)).Compile()();需要注意的是,您需要知道方法签名,尽管您可以编写动态构建表达式的代码以容纳多个签名之一。您可能无法一直使用此技术,但是当您这样做时,这是最佳选择。出于所有意图和目的,这就像给任何其他代表打电话一样。如果您进行多次调用,它也比反射更快(在这种情况下只编译一次并保留已编译委托的句柄)。我有一个类似的问题,并想出这个://////AttemptstothrowtheinnerexceptionoftheTargetInvocationException//////[DebuggerHidden]privatestaticvoidThrowInnerException(TargetInvocationExceptionex){if(ex.InnerException==null){thrownewNullReferenceException("TargetInvocationException不包含InnerException",ex);异常异常=空;try{//假设类型异常有“new(Stringmessage,ExceptioninnerException)”签名}catch{//构造函数没有正确的构造函数,吃掉错误并在下面抛出内部异常}if(exception==null||exception.InnerException==null||ex.InnerException.Message!=exception.Message){//无法正确创建新异常。退回到只抛出内部异常throwex.InnerException;抛出异常;}它的使用示例如下:以上就是C#学习教程:保留动态调用方法异常分享的所有内容。如果对大家有用,需要详细了解C#学习教程,希望大家多多关注——试试]{myType)}).Invoke(null,parameters);}catch(TargetInvocationExceptionex){ThrowInnerException(ex);thrownewException("ThrowInnerException没有抛出异常");}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
