2009-12-11 14 views
19

Ho una classe di eccezioni personalizzata che contiene alcuni campi aggiuntivi. Voglio che vengano scritti nel metodo ToString(), ma se implemento il mio ToString(), perdo altre cose utili (come scrivere il nome del tipo di eccezione, i dati di eccezione interni e la traccia dello stack).C#: Override del metodo ToString() per le eccezioni personalizzate

Qual è il modo migliore/schema per implementare il proprio metodo ToString() per tali eccezioni? Idealmente dovrebbe riutilizzare il meccanismo esistente, ma essere formattato in modo simile all'implementazione predefinita ToString().

UPDATE: prepending o aggiungendo i miei campi personalizzati al base.ToString() testo non è IMHO l'ideale, per esempio

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 i campi personalizzati vengono scritti alla fine del (potenzialmente lungo) descrizione dell'eccezione. D'altra parte, voglio che il tipo di eccezione sia la prima informazione scritta nella descrizione.

UPDATE 2: Ho implementato una soluzione per questo, cercare la mia risposta qui sotto.

+0

Sto cercando la stessa cosa, voglio aggiungere alcune informazioni extra al di fuori del campo Messaggio, ma voglio mantenere il formato ToString, con tutte le tracce dello stack e le eccezioni interne su di esso. Sarebbe interessante vedere il codice per Exception.ToString() e copiarlo aggiungendo ulteriori informazioni. – pauloya

+0

Bene, il codice copre la maggior parte delle cose che hai menzionato. Anche se in seguito mi sono ricordato che avrei potuto usare il dizionario di Exception.Data per archiviare le mie cose personalizzate. Immagino che in tal caso questo sarebbe reso con l'implementazione predefinita di ToString(), ma non l'ho ancora provato. –

risposta

10

OK, questo è ciò che mi è venuta. Ho implementato una classe di estensione che replica il meccanismo originale per la formattazione delle eccezioni, ma con un tocco: un delegato un'azione personalizzata che fornisce un plug-in per la formattazione dei campi personalizzati:

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(); 
    } 
} 

ora è possibile utilizzare questo metodo in le proprie implementazioni ToString() senza duplicare il codice di formattazione:

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

È possibile aggiungere manualmente i dati predefiniti alla stringa restituita da ToString, osservando le proprietà delle eccezioni. Ad esempio, il seguente simulerà i dati restituiti per default con il metodo di un'eccezione ToString (assumendo non ci sono eccezioni interni):

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

Oppure, si potrebbe semplicemente aggiungere (o anteporre) i dati restituiti dal base.ToString al informazioni che vuoi aggiungere.

+1

Questa sembra la soluzione più vicina a ciò che avevo in mente. Anche se hai dimenticato di scrivere InnerException;) –

1

All'interno del base.ToString chiamata di override() e modificare la stringa risultante alle vostre esigenze ...

10

È possibile eseguire l'override del metodo ToString() per inserire il tuo informazioni personalizzate, e ancora chiamare l'eccezione base di default ToString() in questo modo:

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

Se stai principalmente a guardarli nel debugger, quindi è possibile utilizzare l'attributo [DebuggerDisplay] per specificare la formattazione e non toccare il metodo esistente ToString.

In caso contrario, basta sovraccarico ToString ed essere sicuri di chiamare la versione della classe base base.ToString()

+1

Anche se non quello che stavo cercando, +1 per menzionarlo. –

18

Questo è tutto eccessivo. La tua eccezione dovrebbe semplicemente sovrascrivere la proprietà del messaggio.

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

Il metodo ToString predefinito per la classe Exception è fondamentalmente "ClassName: Message --> InnerException.ToString() StackTrace". Quindi, sovrascrivendo il messaggio, il testo del messaggio viene posizionato esattamente dove dovrebbe essere.

+0

Ciò funziona, a meno che non si stia percorrendo questa strada per iniettare una traccia dello stack personalizzata. – yoyo

+0

@yoyo, sì ma non era un requisito dell'OP – Daryl

+0

Totalmente vero, e la tua risposta è buona. (Sono venuto qui cercando qualcosa di leggermente diverso.) – yoyo

Problemi correlati