2009-08-03 12 views
17

Tengo una clase con varios métodos y quiero tener un controlador de excepción para todos ellos. Existen muchos de estos métodos y tienen diferentes parámetros, que sería feo escribir try/catch para cada uno de ellos.One Exception handler para todas las excepciones de una CLASE

Quizás conozca una forma en la que pueda hacerlo con un manejador de excepción único en su clase, que se encargará de todos ellos.

ACTUALIZACIÓN:


Muchos me preguntan por qué. La razón es que estoy llamando a una fuente de datos con varios métodos. así que mi clase tiene funciones getData1, gedData2, getData3, getData4, ...., getDataN. El problema es que no hay forma de verificar si la conexión aún está abierta y crear una nueva conexión es muy costoso. Así que estoy tratando de reutilizar la conexión y si la conexión en la próxima llamada ha fallado, la veré, volveré a conectar e intentaré de nuevo. Es por eso que necesito este try/catch all block.

Para hacer esto para todas las funciones:

try{  
    datasource.getData() 
} 
catch(ConnectionException) 
{ 
    datasource.Connect(); 
    datasource.getData() 
} 

Gracias

+0

Sé que es una vieja pregunta, pero quería decir que aunque estoy básicamente de acuerdo con las respuestas a continuación, que se presentaron el día en que se formuló la pregunta, hay momentos en que esta capacidad sería muy útil. Husayt describió uno arriba y encontré esta pregunta porque tengo otro escenario. A pesar de que la respuesta de Jack Allan no funciona para mi escenario, lo voté por encima porque es útil en otras situaciones y es muy inteligente, en mi humilde opinión. Dicho esto, antes de usar la "solución" de Jack, asegúrese de que no haya otra forma de estructurar su código para evitar la necesidad de esto por completo. –

+0

No existe tal mecanismo, ni debería haberlo, en mi humilde opinión. No es coherente con la forma en que se pasa el flujo de control. No importa que lo que tienes que hacer sea "feo". No importa que la solución que haya hecho requiera escribir un código adicional. Lo que importa es que pueda escribir software que sea fácil de entender y mantener más tarde, cuando usted (u otra persona) haya olvidado los detalles originales. Si un método necesita hacer algo cuando ocurre una excepción, entonces DEBE haber algo en el método que indique qué hacer. Ésto es una cosa buena. – ToolmakerSteve

+0

Por cierto, he votado a favor la pregunta, porque creo que esta es una GRAN pregunta. Es legítimo, y útil para otros, QUERER hacer esto. Comprender por qué no hay una manera de hacer esto, y entender lo que se debe hacer (lo que ya hiciste, en tu pregunta, aunque no te gustó el resultado), será útil para los demás. – ToolmakerSteve

Respuesta

19

Se puede usar un delegado para pasar el código de su método en un solo intento de captura como el siguiente ejemplo:

private void GlobalTryCatch(Action action) 
    { 
     try 
     { 
      action.Invoke(); 
     } 
     catch (ExpectedException1 e) 
     { 
      throw MyCustomException("Something bad happened", e); 
     } 
     catch (ExpectedException2 e) 
     { 
      throw MyCustomException("Something really bad happened", e); 
     } 
    } 

    public void DoSomething() 
    { 
     GlobalTryCatch(() => 
     { 
      // Method code goes here 
     }); 
    } 
1

No creo que hay. Podría mover el try/catch a la persona que llama, pero ese diseño no es muy bueno. Puede que sea mejor para separarlo a cabo en otra clase, y utilizar la reflexión para llamar a los métodos, así:

public class MyClass {} 
public class MySafeClass { 
    public void CallMethod(string name, object[] param) { 
     Type t = typeof(MyClass); 
     MyClass mc = new MyClass(); 
     try { 
      t.GetMethod(name).Invoke(mc, param); 
     } 
     catch { 
      //...; 
     } 
    } 

}

Pero no se debe! No es una buena práctica.

Otro método sigue utilizando try/catch pero tener un único método para lanzar excepciones, etc de nuevo al usuario:

public class MyClass { 
    void DoException(string message) { 
     throw new Exception(message); 
    } 
} 

Pero eso todavía no es tan bueno una opción.

No veo por qué sería feo, incluso si solo envuelve todo el método en una prueba/captura con un mensaje. Eso podría ser factible.

También es una mejor opción simplemente dejarlos y pasarlos de nuevo a la persona que llama, quizás en try/finally.

No es exactamente difícil probar/capturar todo, especialmente con los fragmentos en Visual Studio y SharpDevelop.

+0

Gracias por responder. Quizás al buscar en la actualización de la pregunta, puedas ver mis razones. – husayt

1

Esto suena como un problema con su diseño. ¿Puede explicar exactamente qué excepciones está tratando de detectar y por qué, y podemos intentar ayudarlo?

+0

sí, probablemente necesito dar más contexto, verifique mi actualización a la pregunta, por favor. – husayt

1

Las excepciones no están realmente relacionadas con la clase, sino que están orientadas al método/callstack. Un objeto, en general, no debe tratar de manejar excepciones desde sus propios métodos. Depende de las personas que llaman de esos métodos.

0

es posible que desee probar/capturar su método principal, aunque considero que se trata de un mal uso grave del manejo de excepciones, excepto que desea agregar un registrador o algo así.

+0

Necesito algo solo para esa clase y lo manejo dentro de esa clase Thnks – husayt

12

No puedo imaginar ninguna razón por la que puede beneficiarse de manejar todas las excepciones en una clase utilizando un único método (se puede elaborar? Tengo curiosidad ...)

De todos modos, puede utilizar AOP (Programación Orientada a Aspectos) técnicas para inyectar (estáticamente o en tiempo de ejecución) código de manejo de excepciones alrededor de los métodos de su clase.

Hay una buena biblioteca de montaje post-procesamiento de llamada PostSharp que se puede configurar mediante atributos sobre los métodos de su clase:

Es posible definir un aspecto como este (del sitio Web PostSharp):

public class ExceptionDialogAttribute : OnExceptionAspect 
{ 
    public override void OnException(MethodExecutionEventArgs eventArgs) 
    { 
     string message = eventArgs.Exception.Message; 
     MessageBox.Show(message, "Exception"); 
     eventArgs.FlowBehavior = FlowBehavior.Continue; 
    } 
} 

Y luego vamos a aplicar el atributo a los métodos que desea ver excepciones, como esto:

public class YourClass { 

    // ... 

    [ExceptionDialog] 
    public string DoSomething(int param) { 
     // ... 
    } 
} 

También puede aplicar el atributo a la clase entera, así:

[ExceptionDialog] 
public class YourClass { 
    // ... 
    public string DoSomething(int param) { 
     // ... 
    } 
    public string DoSomethingElse(int param) { 
     // ... 
    } 
} 

Esto aplicará el consejo (el código de control de excepciones) a cada método en la clase.

+1

Buena respuesta. Solo para su información, parece que PostSharp cambió la firma OnException a OnException (MethodExecutionArgs eventArgs) para el método virtual. – joshmcode

+0

Solo quería agregar mi caso de uso para esto, estoy creando un mod para un juego. En el caso de que se produzca una excepción que no capté, me gustaría que mi mod se anule el registro y registre el error (en lugar de bloquear el juego). Así que esto es conveniente. –

Cuestiones relacionadas