sentencia que programacion lenguaje funciona else ejemplos como c# .net exception

que - ¿Cómo volver a generar InnerException sin perder el seguimiento de pila en C#?



que es if else en programacion (9)

Aún más reflexión ...

catch (TargetInvocationException tiex) { // Get the _remoteStackTraceString of the Exception class FieldInfo remoteStackTraceString = typeof(Exception) .GetField("_remoteStackTraceString", BindingFlags.Instance | BindingFlags.NonPublic); // MS.Net if (remoteStackTraceString == null) remoteStackTraceString = typeof(Exception) .GetField("remote_stack_trace", BindingFlags.Instance | BindingFlags.NonPublic); // Mono // Set the InnerException._remoteStackTraceString // to the current InnerException.StackTrace remoteStackTraceString.SetValue(tiex.InnerException, tiex.InnerException.StackTrace + Environment.NewLine); // Throw the new exception throw tiex.InnerException; }

Tenga en cuenta que esto puede fallar en cualquier momento, ya que los campos privados no forman parte de la API. Ver más discusión sobre Mono bugzilla .

Estoy llamando, a través de la reflexión, un método que puede causar una excepción. ¿Cómo puedo pasar la excepción a mi interlocutor sin que se coloque alrededor del reflejo de envoltura?
Estoy reenviando la InnerException, pero esto destruye la traza de la pila.
Código de ejemplo:

public void test1() { // Throw an exception for testing purposes throw new ArgumentException("test1"); } void test2() { try { MethodInfo mi = typeof(Program).GetMethod("test1"); mi.Invoke(this, null); } catch (TargetInvocationException tiex) { // Throw the new exception throw tiex.InnerException; } }


Chicos, son geniales ... pronto seré un nigromante.

public void test1() { // Throw an exception for testing purposes throw new ArgumentException("test1"); } void test2() { MethodInfo mi = typeof(Program).GetMethod("test1"); ((Action)Delegate.CreateDelegate(typeof(Action), mi))(); }


Creo que lo mejor sería poner esto en tu bloque catch:

throw;

Y luego extraer la excepción de la creencia posterior.


En .NET 4.5 ahora existe la clase ExceptionDispatchInfo .

Esto le permite capturar una excepción y volver a lanzarla sin cambiar el seguimiento de la pila:

try { task.Wait(); } catch(AggregateException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); }

Esto funciona en cualquier excepción, no solo en AggregateException .

Se introdujo debido a la característica de lenguaje await C #, que desenvuelve las excepciones internas de las instancias de AggregateException para hacer que las características del lenguaje asíncrono se parezcan más a las características del lenguaje síncrono.


Es posible conservar la traza de pila antes de volver a generar sin reflexión:

static void PreserveStackTrace (Exception e) { var ctx = new StreamingContext (StreamingContextStates.CrossAppDomain) ; var mgr = new ObjectManager (null, ctx) ; var si = new SerializationInfo (e.GetType (), new FormatterConverter ()) ; e.GetObjectData (si, ctx) ; mgr.RegisterObject (e, 1, si) ; // prepare for SetObjectData mgr.DoFixups () ; // ObjectManager calls SetObjectData // voila, e is unmodified save for _remoteStackTraceString }

Esto desperdicia muchos ciclos en comparación con las llamadas a InternalPreserveStackTrace través del delegado en caché, pero tiene la ventaja de confiar solo en la funcionalidad pública. Aquí hay un par de patrones de uso comunes para las funciones de preservación del seguimiento de la pila:

// usage (A): cross-thread invoke, messaging, custom task schedulers etc. catch (Exception e) { PreserveStackTrace (e) ; // store exception to be re-thrown later, // possibly in a different thread operationResult.Exception = e ; } // usage (B): after calling MethodInfo.Invoke() and the like catch (TargetInvocationException tiex) { PreserveStackTrace (tiex.InnerException) ; // unwrap TargetInvocationException, so that typed catch clauses // in library/3rd-party code can work correctly; // new stack trace is appended to existing one throw tiex.InnerException ; }


Nadie ha explicado la diferencia entre ExceptionDispatchInfo.Capture( ex ).Throw() y un throw simple, así que aquí está.

La forma completa de volver a emitir una excepción capturada es usar ExceptionDispatchInfo.Capture( ex ).Throw() (solo disponible desde .Net 4.5).

A continuación se presentan los casos necesarios para probar esto:

1.

void CallingMethod() { //try { throw new Exception( "TEST" ); } //catch { // throw; } }

2.

void CallingMethod() { try { throw new Exception( "TEST" ); } catch( Exception ex ) { ExceptionDispatchInfo.Capture( ex ).Throw(); throw; // So the compiler doesn''t complain about methods which don''t either return or throw. } }

3.

void CallingMethod() { try { throw new Exception( "TEST" ); } catch { throw; } }

4.

void CallingMethod() { try { throw new Exception( "TEST" ); } catch( Exception ex ) { throw new Exception( "RETHROW", ex ); } }

El caso 1 y el caso 2 le darán un seguimiento de la pila donde el número de línea del código fuente para el método CallingMethod es el número de línea de la línea de throw new Exception( "TEST" ) .

Sin embargo, el caso 3 le dará un seguimiento de la pila donde el número de línea del código fuente para el método CallingMethod es el número de línea de la llamada de throw . Esto significa que si la línea de throw new Exception( "TEST" ) está rodeada por otras operaciones, no tiene idea de a qué número de línea se lanzó la excepción.

El caso 4 es similar al caso 2 porque el número de línea de la excepción original se conserva, pero no es un retorno real porque cambia el tipo de la excepción original.


Otro código de ejemplo que utiliza la serialización / deserialización de excepciones. No requiere que el tipo de excepción real sea serializable. También utiliza únicamente métodos públicos / protegidos.

static void PreserveStackTrace(Exception e) { var ctx = new StreamingContext(StreamingContextStates.CrossAppDomain); var si = new SerializationInfo(typeof(Exception), new FormatterConverter()); var ctor = typeof(Exception).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(SerializationInfo), typeof(StreamingContext) }, null); e.GetObjectData(si, ctx); ctor.Invoke(e, new object[] { si, ctx }); }


Primero: no pierda la excepción TargetInvocationException: es información valiosa cuando querrá depurar las cosas.
Segundo: Envuelva la TIE como InnerException en su propio tipo de excepción y coloque una propiedad OriginalException que enlaza con lo que necesita (y mantenga intacta toda la pila de llamadas).
Tercero: Deja que TIE salga de tu método.


public static class ExceptionHelper { private static Action<Exception> _preserveInternalException; static ExceptionHelper() { MethodInfo preserveStackTrace = typeof( Exception ).GetMethod( "InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic ); _preserveInternalException = (Action<Exception>)Delegate.CreateDelegate( typeof( Action<Exception> ), preserveStackTrace ); } public static void PreserveStackTrace( this Exception ex ) { _preserveInternalException( ex ); } }

Llame al método de extensión en su excepción antes de lanzarlo, conservará el seguimiento de la pila original.