Todos los demás ya han escrito cuál es el diseño correcto de su clase Database
, por lo que no lo repetiré. Sin embargo, no vi ninguna explicación de por qué lo que quieres no es posible. Entonces aquí va.
Lo que quiere hacer es detectar, durante la llamada al Dispose
, que se llama a este método en el contexto de una excepción. Cuando pueda hacer esto, los desarrolladores no tendrán que llamar al Commit
explícitamente. Sin embargo, el problema aquí es que no hay manera de detectar esto de manera confiable en .NET. Si bien existen mecanismos para consultar el último error lanzado (como HttpServerUtility.GetLastError), estos mecanismos son específicos del host (por lo que ASP.NET tiene otro mecanismo como formularios de Windows, por ejemplo). Y aunque podría escribir una implementación para una implementación de host específica, por ejemplo, una implementación que solo funcionaría en ASP.NET, hay otro problema más importante: ¿qué ocurre si se usa su clase Database
o se crea dentro del contexto de una excepción? ? Aquí se muestra un ejemplo:
try
{
// do something that might fail
}
catch (Exception ex)
{
using (var database = new Database())
{
// Log the exception to the database
database.Add(ex);
}
}
Cuando se utiliza la clase Database
en el contexto de un Exception
, como en el ejemplo anterior, cómo se supone que su método de Dispose
saber que todavía debe comprometerse? Puedo pensar en formas de evitar esto, pero será bastante frágil y propenso a errores. Para dar un ejemplo.
Durante la creación del Database
, puede comprobar si se llama en el contexto de una excepción, y si ese es el caso, almacene esa excepción. Durante el tiempo en que se llama al Dispose
, comprueba si la última excepción lanzada difiere de la excepción en caché. Si difiere, deberías retroceder. Si no, cometer.
Si bien esto parece una buena solución, ¿qué pasa con este ejemplo de código?
var logger = new Database();
try
{
// do something that might fail
}
catch (Exception ex)
{
logger.Add(ex);
logger.Dispose();
}
En el ejemplo se ve que un ejemplo Database
se crea antes de que el bloque try. Por lo tanto, no puede detectar correctamente que no podría retroceder. Si bien este podría ser un ejemplo artificial, muestra las dificultades que tendrá que enfrentar al tratar de diseñar su clase de una manera que no sea necesaria una llamada explícita a Commit
.
Al final harás que tu clase Database
sea difícil de diseñar, difícil de mantener y nunca lo harás bien.
Como todos los demás ya se ha dicho, un diseño que necesita una explícita Commit
o Complete
llamada, sería más fácil de implementar, fácil de hacerlo bien, más fácil de mantener, y da código de uso que es más fácil de leer (por ejemplo, porque mira lo que los desarrolladores esperan).
última nota, si usted está preocupado por los desarrolladores de olvidarse de llamar a este método Commit
: usted puede hacer algunas comprobaciones en el método Dispose
para ver si se le llama sin Commit
se llama y escribir en la consola o un punto de ruptura, mientras depuración Codificar una solución así sería mucho más fácil que tratar de deshacerse del Commit
en absoluto.
Actualización: Adrian wrote una alternativa intersting a usar HttpServerUtility.GetLastError. Como señala Adrian, puede usar Marshal.GetExceptionPointers()
, que es una forma genérica que funcionaría en la mayoría de los hosts. Tenga en cuenta que esta solución tiene los mismos inconvenientes explicados anteriormente y que llamar a la clase Marshal
solo es posible en plena confianza
Adrián, lo tienes, no quiero que te enseñen sobre los usos de patrones, solo una solución técnica, funcionó maravillosamente. –
Por favor, eche un vistazo a mi respuesta. Intento explicar por qué es una mala idea buscar excepciones dentro de un método 'Dispose'. – Steven
@Steven: como la mayoría de las respuestas (incluida la suya) han acordado, este no es un patrón inteligente para usar. Aun así, la pregunta original preguntó si es * posible * saber si se ha lanzado una excepción cuando estoy en un método 'Dispose', que es lo que muestra mi respuesta, incluso si tiene problemas asociados. – adrianbanks