2009-12-11 10 views
19

Tengo una clase de excepción personalizada que contiene algunos campos adicionales. Quiero que se escriban en el método ToString(), pero si implemento mi propio ToString(), pierdo algunas otras cosas útiles (como escribir el nombre del tipo de excepción, los datos de la excepción interna y el seguimiento de la pila).C#: Anulación del método ToString() para excepciones personalizadas

¿Cuál es la mejor forma/patrón para implementar su propio método ToString() para tales excepciones? Lo ideal sería reutilizar el mecanismo existente, pero se formatee de forma similar a la implementación predeterminada ToString().

ACTUALIZACIÓN: prepending o de agregar mis campos personalizados a la base.ToString() texto no es mi humilde opinión ideales, por ejemplo

PimTool.Utilities.OERestServiceUnavailableException: test ---> System.InvalidOperationException: inner message 
    --- End of inner exception stack trace --- 
    at PimTool.Tests.Services.OE.OERestClientTests.ExceptionsLogging() in D:\svn\NewPimTool\PimTool.Tests\Services\OE\OERestClientTests.cs:line 178, 
    StatusCode=0, message='test', requestId='535345' 

significa que los campos personalizados se escriben al final de la (potencialmente larga) descripción de la excepción. Por otro lado, quiero que el tipo de excepción sea la primera información escrita en la descripción.

ACTUALIZACIÓN 2: He implementado una solución para esto, busque mi propia respuesta a continuación.

+0

Estoy buscando lo mismo, quiero agregar algo de información extra afuera, no en el campo Mensaje, pero quiero que se mantenga el formato ToString, con todas las trazas de la pila y las excepciones internas. Sería interesante ver el código de Exception.ToString() y copiarlo agregando más información. – pauloya

+0

Bueno, el código cubre la mayoría de las cosas que mencionaste. Aunque más tarde recordé que podría haber usado el diccionario Exception.Data para almacenar mis cosas personalizadas. Supongo que en ese caso esto se representaría con la implementación predeterminada de ToString(), pero aún no lo he probado. –

Respuesta

10

bien, esto es lo que ocurrió. He implementado una clase de extensión que replica el mecanismo original para formatear excepciones, pero con un giro: un delegado de encargo de acción que proporciona un plug-in para dar formato a los campos personalizados:

public static class ExceptionFormatterExtensions 
{ 
    public static string ExceptionToString (
     this Exception ex, 
     Action<StringBuilder> customFieldsFormatterAction) 
    { 
     StringBuilder description = new StringBuilder(); 
     description.AppendFormat("{0}: {1}", ex.GetType().Name, ex.Message); 

     if (customFieldsFormatterAction != null) 
      customFieldsFormatterAction(description); 

     if (ex.InnerException != null) 
     { 
      description.AppendFormat(" ---> {0}", ex.InnerException); 
      description.AppendFormat(
       "{0} --- End of inner exception stack trace ---{0}", 
       Environment.NewLine); 
     } 

     description.Append(ex.StackTrace); 

     return description.ToString(); 
    } 
} 

Ahora puede utilizar este método en su propio ToString() implementaciones sin duplicar el código de formato:

public override string ToString() 
    { 
     return this.ExceptionToString(
      description => 
      { 
       description.AppendFormat(
        ", HttpStatusCode={0}, RequestId='{1}'", 
        httpStatusCode, 
        RequestId); 
      }); 
    } 
12

Puede agregar manualmente los datos predeterminados a la cadena devuelta por ToString, mirando las propiedades de la excepción. Por ejemplo, lo siguiente será simular los datos devueltos por defecto por el método de una excepción de ToString (asumiendo que no hay excepciones internas):

string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace); 

O, simplemente puede añadir (o anteponer) los datos devueltos por base.ToString a la información que desea agregar

+1

Esta parece ser la solución más cercana a lo que tenía en mente. Aunque olvidó escribir la InnerException;) –

1

Dentro de la llamada base.ToString anulación() y modificar la cadena resultante a sus necesidades ...

10

Puede reemplazar el método ToString() para incluir su propia información personalizada, y todavía llamar a la Excepción base por defecto ToString() así:

public class MyException : Exception 
{ 
    public string CustomField { get; set; } 
    public override string ToString() 
    { 
     return CustomField + Environment.NewLine + base.ToString(); 
    } 
} 
4

Si está principalmente mirarlos en el depurador, a continuación, puede utilizar el atributo [DebuggerDisplay] para especificar su formato y no tocar la ToString método existente.

De lo contrario, simplemente sobrecargue ToString y asegúrese de llamar a la versión de la clase base base.ToString()

+1

Aunque no es lo que estaba buscando, +1 por mencionarlo. –

18

todo esto es una exageración. Su excepción debe anular la propiedad del mensaje.

public override String Message { 
    get { 
     return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'", 
        httpStatusCode, 
        RequestId); 
    } 
} 

El método ToString por defecto para la clase de excepción es básicamente "ClassName: Message --> InnerException.ToString() StackTrace". Por lo tanto, anular el mensaje coloca el texto del mensaje exactamente donde debería estar.

+0

Eso funciona a menos que vaya por este camino para inyectar un seguimiento de pila personalizado. – yoyo

+0

@yoyo, sí, pero eso no era un requisito del OP – Daryl

+0

Totalmente cierto, y su respuesta es buena. (Vine aquí buscando algo un poco diferente.) – yoyo

Cuestiones relacionadas