2012-06-18 32 views
5

Programiści w moim zespole czasami otwierają transakcję i zapominają dołączyć instrukcję scope.Complete() (patrz blok kodu poniżej). Wszelkie pomysły na temat sposobów alboC# - Jak sprawdzić brakujące instrukcje scope.Complete()?

(1) przeszukać nasze rozwiązanie brakuje scope.Complete() oświadczenia lub

(2) mają Visual Studio automatycznie podświetlenie lub podnieść ostrzeżenie dla brakujących scope.Complete() sprawozdania ?

Oto linia tęsknimy:

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

Co Próbowałem
 
Próbowałem, używając wzorca ReSharper zwyczaj ten cel, bez powodzenia. Idealnie chciałbym szukać czegoś podobnego:

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

Jednak ReSharper akceptuje tylko wyrażeń regularnych dla identyfikatorów, a nie wypowiedzi, więc nie wydaje się działać (http://www.jetbrains.com/resharper/webhelp/Reference__Search_with_Pattern.html).

Wszelkie pomysły? Jestem również otwarty na używanie innych wtyczek lub narzędzi.

Dzięki,
Ben

+1

Nie testują swojego kodu? – Magnus

+0

Widziałem to już wcześniej z testem. Poprzez odbicie można określić, czy metoda jest wywoływana w instancji. Jeśli tak nie jest, test kończy się niepowodzeniem. –

+1

Liczę z NDependem, że można ustawić regułę, aby szukać metod, w których liczba zastosowań ctor "TransactionScope" była mniejsza niż liczba zastosowań "Complete". – AakashM

Odpowiedz

3

NDepend pewnością może pomóc, ale nie może sprawdzić, 100% tego, co prosicie. NDepend nie wie o wewnętrznych elementach metody (kolejność wywołań metod). Tak więc w najlepszym wypadku można napisać code rule over LINQ (CQLinq) że sprawdzi, czy metoda jest stworzenie TransactionScope, to przynajmniej musi wywołać TransactionScope.Complete():

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

Zauważ, że jeśli deweloperzy są na tyle zdyscyplinowany, aby uniknąć tworzenia wielu TransactionScope w jednej metody , ta zasada powinna działać dla ciebie.

+0

Doskonały. Dzięki wielkie! –

4

Mógłbyś zmusić programistów użyć niestandardowego API zamiast scope.Complete rzeczy niskiego poziomu?

Zamknięcie wymusi użycie .Complete():

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

Następnie można zrobić:

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

Dzięki za odpowiedź! To prawda, możemy zreorganizować nasze dotychczasowe transakcje, aby używać niestandardowego API podobnego do tego, który napisałeś, a następnie spróbuj zmusić programistów do korzystania z tego API dla przyszłego kodu. Myślę, że trudnym punktem byłoby zreorganizowanie wszystkich transakcji, ponieważ mamy już dużą bazę kodu. Nie jestem pewien, czy byłoby to warte poświęcenia czasu. Myśląc o tym ... –

0

Nie znam żadnej istniejącej wtyczki R #, która to sprawdza, ale na pewno można utworzyć własną. Wszystko, co musisz zrobić, to wykryć instrukcję using z deklaracją zmiennej typu TransactionScope, a następnie powtórzyć instrukcje zawarte szukając połączenia Complete().

Jeśli jesteś zainteresowany zrobieniem tego, polecam pobrać ReSharper SDK i sprawdzić Plugin Development Guide.