2009-07-08 13 views
5

Quando si tratta di eccezioni personalizzate, di solito ereditano da Exception e quindi aggiungere alcuni campi/proprietà alla mia classe di eccezione per memorizzare alcune informazioni aggiuntive:Come devo archiviare i dati all'interno di eccezioni personalizzate?

public class MyException : Exception 
{ 
    public int ErrorCode{get;set;} 

    public MyException() 
    {} 
} 

Nell'esempio precedente, il valore ErrorCode viene memorizzato nella un'eccezione , il che significa che devo aggiungerlo e ritirarlo se dall'oggetto SerializationInfo nel costruttore protetto e il metodo sostituito da GetObjectData.

La classe Exception ha una proprietà Data, che secondo MSDN:

Ottiene un insieme di coppie chiave/valore che forniscono informazioni definite dall'utente ulteriori circa l'eccezione.

Se devo conservare il codice di errore all'interno del Data, otterrà serializzato per me dalla classe Exception (secondo Reflector), il che significa che la mia classe di eccezione ora assomiglia:

public class MyException : Exception 
{ 
    public int ErrorCode 
    { 
     get {return (int) Data["ErrorCode"];} 
     set {Data["ErrorCode"] = value;} 
    } 

    public MyException() 
    {} 
} 

Questo significa che mentre c'è ancora un po 'di lavoro da fare nell'affrontare il get/set del codice di errore (come affrontare gli errori di casting e le situazioni in cui il codice di errore potrebbe non essere nel dizionario), non devo preoccuparmi di serializzare/deserializzandolo.

Questo è solo due diversi modi per ottenere la stessa cosa, o in un modo si hanno dei vantaggi chiari rispetto all'altro (a parte quelli che ho già menzionato)?

risposta

1

Eviterei di utilizzare Dati poiché non è sotto il tuo controllo, ad es. qualche codice potrebbe decidere di sovrascrivere il valore "ErrorCode". Usa invece la proprietà e implementa la serializzazione. Io uso il seguente codice per testare tutte le mie eccezioni personalizzate per assicurarmi di averle implementate correttamente.

public static void TestCustomException<T>() where T : Exception 
{ 
    var t = typeof(T); 

    //Custom exceptions should have the following 3 constructors 
    var e1 = (T)Activator.CreateInstance(t, null); 

    const string message = "message"; 
    var e2 = (T)Activator.CreateInstance(t, message); 
    Assert.AreEqual(message, e2.Message); 

    var innerEx = new Exception("inner Exception"); 
    var e3 = (T)Activator.CreateInstance(t, message, innerEx); 
    Assert.AreEqual(message, e3.Message); 
    Assert.AreEqual(innerEx, e3.InnerException); 

    //They should also be serializable 
    var stream = new MemoryStream(); 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(stream, e3); 
    stream.Flush(); 
    stream.Position = 0; 
    var e4 = (T)formatter.Deserialize(stream); 
    Assert.AreEqual(message, e4.Message); 
    Assert.AreEqual(innerEx.ToString(), e4.InnerException.ToString()); 
} 
0

Si dovrebbe andare con la prima soluzione. Non riesco a vedere molto valore nella proprietà Data, a meno che non si preveda di generare istanze Exception di riga con informazioni allegate.

Se si dispone del proprio tipo di eccezione, utilizzare invece le proprietà: è più pulito e sicuro.

1

Microsoft's own guidelines:

fanno eccezioni serializzabile. Un'eccezione deve essere serializzabile per funzionare correttamente attraverso il dominio dell'applicazione e i limiti remoti.

Vorrei archiviarlo nella proprietà Data che purtroppo consentirebbe al codice esterno di modificare il valore senza consenso, oppure utilizzare la soluzione 1 (nell'esempio) ma renderlo serializzabile. Alla fine probabilmente opterei per la soluzione 1, quindi posso essere sicuro che il valore non cambia mai.

5

Se si sta dando la briga di creare la propria eccezione, non è necessario la proprietà Data. I dati sono utili quando si desidera archiviare un po 'di informazioni aggiuntive in una classe di eccezioni esistente, ma non si desidera creare la propria classe di eccezioni personalizzata.

Problemi correlati