2009-08-03 14 views
17

Ho una classe con numero di metodi e voglio avere un gestore di eccezioni per tutti. Ci sono così tanti di questi metodi e hanno parametri diversi, che sarebbe brutto scrivere try/catch per ognuno di essi.Un gestore di eccezioni per tutte le eccezioni di una classe

Forse conosci un modo in cui posso farlo con un gestore di eccezioni di una classe, che gestirà tutte.

UPDATE:


Molti di voi mi chiedono perché. Il motivo è che sto chiamando un'origine dati con vari metodi. quindi la mia classe ha funzioni getData1, gedData2, getData3, getData4, ...., getDataN. Il problema è che non c'è modo di verificare se la connessione è ancora aperta e la creazione di una nuova connessione è molto costosa. Quindi sto cercando di riutilizzare la connessione e se la connessione alla prossima chiamata non è andata a buon fine, lo prenderei e riconnetterò e riproverò. Ecco perché ho bisogno di questo try/catch all block.

di fare questo per tutte le funzioni:

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

Grazie

+0

So che è una vecchia questione, ma volevo dire che, anche se io per lo più d'accordo con le risposte di seguito che sono state presentate il giorno in cui è stata posta la domanda, ci sono momenti in cui questa capacità sarebbe molto utile. ne ho descritto uno sopra e ho trovato questa domanda perché ho un altro scenario. Anche se la risposta di Jack Allan non funziona per il mio scenario, l'ho svalutato perché è utile in altre situazioni ed è molto intelligente, IMHO. Detto questo, prima di usare la "soluzione" di Jack assicurati che non ci sia un altro modo per strutturare il tuo codice per evitare del tutto la necessità. –

+0

Non esiste un meccanismo del genere - né dovrebbe esserci, IMHO. Non è coerente con il modo in cui viene trasmesso il flusso di controllo. Non importa che quello che devi fare è "brutto". Non importa che la soluzione che hai fatto, richiede la scrittura di codice aggiuntivo. Ciò che conta è che tu sia in grado di scrivere software che sia facile da capire e da mantenere in seguito, quando tu (o qualcun altro) hai dimenticato i dettagli originali. Se un metodo deve fare qualcosa quando si verifica un'eccezione, allora DEVE essere qualcosa nel metodo, che dice cosa fare. Questa è una buona cosa. – ToolmakerSteve

+0

BTW, ho sviato la domanda, perché penso che questa sia una GRANDE domanda. È legittimo e utile per gli altri, VUOLE fare questo. Capire PERCHE 'non c'è un modo per farlo e capire cosa dovrebbe essere fatto (cosa che hai già fatto, nella tua domanda, anche se non ti è piaciuto il risultato), sarà utile per gli altri. – ToolmakerSteve

risposta

19

Si potrebbe utilizzare un delegato per passare il codice del tuo metodo in un unico tentativo di cattura come il seguente esempio:

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

Non credo che ci sia. Potresti spostare il try/catch al chiamante, ma non è un ottimo design. Essa può essere meglio separare fuori in un'altra classe, e utilizzare la reflection per chiamare i metodi, in questo modo:

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 { 
      //...; 
     } 
    } 

}

Ma non dovrebbe! Non è una buona pratica.

Un altro metodo è ancora utilizzando try/catch ma avendo come unico metodo di generare eccezioni, ecc indietro per l'utente:

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

Ma che ancora non è che una buona opzione.

Non vedo perché sarebbe brutto, anche se si avvolge l'intero metodo in un tentativo/cattura con un messaggio. Potrebbe essere fattibile.

È anche un'opzione migliore per lasciarli e restituirli al chiamante, forse in try/finally.

Non è esattamente difficile provare/catturare tutto, specialmente con i frammenti di Visual Studio e SharpDevelop.

+0

Grazie per la risposta. Forse esaminando l'aggiornamento alla domanda potresti vedere le mie ragioni. – husayt

1

Sembra un problema con il tuo progetto. Puoi approfondire esattamente quali eccezioni stai cercando di cogliere e perché e possiamo provare ad aiutarci.

+0

sì, probabilmente ho bisogno di dare più contesto, controlla il mio aggiornamento alla domanda per favore. – husayt

1

Le eccezioni non sono realmente correlate alla classe ma sono orientate al metodo e al callstack. In generale, un oggetto non dovrebbe tentare di gestire le eccezioni dai propri metodi. Dipende dai chiamanti di questi metodi.

0

si potrebbe desiderare di mettere un try/catch sul metodo principale, anche se considero questo un grave abuso di gestione delle eccezioni, tranne che si desidera aggiungere un logger o sth.

+0

ho bisogno di qualcosa solo per quella classe e gestito all'interno di quella classe Thnks – husayt

12

io non riesco a capire alcuna ragione per cui si può beneficiare di gestire tutte le eccezioni in una classe con un unico metodo (si può elaborare? Sono curioso ...)

In ogni caso, è possibile utilizzare Tecniche AOP (Aspect Oriented Programming) per iniettare (staticamente o in runtime) codice di gestione delle eccezioni attorno ai metodi della classe.

C'è una libreria di post-elaborazione buon assemblaggio chiamato PostSharp che è possibile configurare utilizzando gli attributi sui metodi nella tua classe:

È possibile definire un aspetto come questo (dal sito PostSharp):

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

E poi applicherete l'attributo ai metodi che si desidera vedere le eccezioni, come questo:

public class YourClass { 

    // ... 

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

È inoltre possibile applicare l'attributo a tutta la classe, in questo modo:

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

Ciò si applica il consiglio (il codice di gestione delle eccezioni) per ogni metodo nella classe.

+1

Buona risposta. Per la cronaca, sembra che PostSharp abbia modificato la firma di OnException in OnException (MethodExecutionArgs eventArgs) per il metodo virtuale. – joshmcode

+0

Volevo solo aggiungere il mio caso d'uso per questo, sto creando un mod per un gioco. Nel caso in cui venga lanciata un'eccezione che non ho catturato, vorrei che la mia mod si cancellasse da sé e registrasse l'errore (piuttosto che mandare in crash il gioco). Quindi questo è conveniente. –

Problemi correlati