2012-06-18 32 views
5

I programmatori della mia squadra talvolta aprono una transazione e dimenticano di includere l'istruzione scope.Complete() (vedere il blocco di codice di seguito). Tutte le idee sui modi per entrambi iC# - Come faccio a verificare la mancanza di istruzioni scope.Complete()?

(1) cercare la nostra soluzione per la mancanza scope.Complete() dichiarazioni, o

(2) dispone di Visual Studio evidenziare automaticamente o sollevare un avviso per mancante scope.Complete() dichiarazioni ?

Ecco la linea ci manca:

using(TransactionScope scope = new TransactionScope()) 
{ 
     /* Perform transactional work here */ 
     scope.Complete(); <-- we forget this line 
     /* Optionally, include a return statement */ 
} 

Quello che ho cercato
 
Ho provato con un modello personalizzato ReSharper per questo scopo, senza fortuna. Idealmente vorrei cercare qualcosa di simile:

using(TransactionScope scope = new TransactionScope()) 
{ 
    $statements1$ 
    [^(scope.Complete();)] 
    $statements2$ 
} 

Tuttavia, ReSharper accetta solo le espressioni regolari per gli identificatori, non per le dichiarazioni, quindi questo non sembra funzionare (http://www.jetbrains.com/resharper/webhelp/Reference__Search_with_Pattern.html).

Qualche idea? Sono aperto ad usare anche altri plugin o strumenti.

Grazie,
Ben

+1

Non testano il loro codice? – Magnus

+0

Ho visto questo fatto prima con un test. Tramite riflessione è possibile determinare se un metodo viene chiamato su un'istanza. Se non lo è, il test fallisce. –

+1

Penso che con NDepend è possibile impostare una regola per cercare metodi in cui il numero di utilizzi di 'TransactionScope' è inferiore al numero di utilizzi' Completi'. – AakashM

risposta

3

NDepend può certamente aiutare, ma non può controllare il 100% di quello che si sta chiedendo. NDepend non è a conoscenza degli interni del corpo del metodo (ordine delle chiamate al metodo). Quindi nella migliore delle ipotesi, è possibile scrivere una code rule over LINQ (CQLinq) che controllerà che se un metodo è la creazione di un TransactionScope, almeno si deve chiamare TransactionScope.Complete():

warnif count > 0 
from m in Application.Methods 
where m.CreateA("System.Transactions.TransactionScope") && 
    !m.IsUsing("System.Transactions.TransactionScope.Complete()") 
select m 

Si noti che se gli sviluppatori sono disciplinati abbastanza per evitare di creare più TransactionScope in un metodo questa regola dovrebbe funzionare per te.

+0

Eccellente. Grazie mille! –

4

Potrebbe costringere i programmatori di utilizzare un'API personalizzata al posto della roba scope.Complete di basso livello?

Una chiusura forzerà l'utilizzo di .Complete():

public static void Do(this TransactionScope scope, Action action) { 
    using (scope) { 
    action(); 
    scope.Complete(); 
    } 
} 

allora si potrebbe fare:

new TransactionScope().Do(() => /* Transactional stuff */); 
+0

Grazie per la risposta! È vero, potremmo rifattorizzare le nostre transazioni esistenti per utilizzare un'API personalizzata simile a quella che hai scritto, quindi provare a forzare i programmatori a utilizzare questa API per il codice futuro. Penso che il punto difficile sarebbe il refactoring di tutte le transazioni, dal momento che abbiamo già una grande base di codice. Non sono sicuro che ciò varrebbe la pena. Pensandoci ... –

0

Non sono a conoscenza di alcun plug-in R # esistente che controlli questo, ma potresti sicuramente crearne uno tuo. Tutto quello che dovresti fare è rilevare un'istruzione using con una dichiarazione variabile del tipo TransactionScope, quindi iterare le istruzioni contenute cercando la chiamata Complete().

Se sei interessato a farlo, ti consiglio di scaricare lo ReSharper SDK e di controllare lo Plugin Development Guide.

Problemi correlati