2012-06-18 34 views
5

Los programadores de mi equipo a veces abren una transacción y olvidan incluir la instrucción scope.Complete() (ver el bloque de código a continuación). Cualquier ideas sobre aspectos a la deC# - ¿Cómo verifico si faltan las instrucciones scope.Complete()?

(1) buscar nuestra solución para la falta scope.Complete() declaraciones o

(2) tener Visual Studio automáticamente resaltar o elevar una advertencia de falta scope.Complete (declaraciones) ?

Aquí está la línea que se pierda:

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

Lo que he tratado
 
He intentado usar un patrón ReSharper personalizada para este propósito, sin suerte. Lo ideal sería buscar algo como:

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

Sin embargo, ReSharper sólo acepta expresiones regulares de los identificadores, no para los estados, por lo que este no parece trabajar (http://www.jetbrains.com/resharper/webhelp/Reference__Search_with_Pattern.html).

¿Alguna idea? Estoy abierto a usar otros complementos o herramientas también.

Gracias,
Ben

+1

¿No prueban su código? – Magnus

+0

He visto esto hecho antes con una prueba. A través de la reflexión puede determinar si se llama a un método en una instancia. Si no es así, la prueba falla. –

+1

Creo que con NDepend podría configurar una regla para buscar métodos en los que el número de usos del ctor de 'TransactionScope' fuera menor que el número de usos' completos'. – AakashM

Respuesta

3

NDepend sin duda puede ayudar, pero no puede comprobar el 100% de lo que está pidiendo. NDepend no sabe acerca de las partes internas del método (orden de las llamadas al método). Así que a lo mejor, se puede escribir un code rule over LINQ (CQLinq) que comprobará que si un método es la creación de un TransactionScope, al menos debe llamar TransactionScope.Complete():

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

Tenga en cuenta que si los desarrolladores son disciplinados suficiente para evitar la creación de múltiples TransactionScope en un método , esta regla debería funcionar para ti.

+0

Excelente. ¡Muchas gracias! –

4

Podría obligar a los programadores utilizar una API personalizada en lugar de las cosas scope.Complete de bajo nivel?

Un cierre forzará el uso de .Complete():

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

entonces se podría hacer:

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

¡Gracias por la respuesta! Es cierto, podríamos refactorizar nuestras transacciones existentes para usar una API personalizada similar a la que usted ha escrito, y luego tratar de forzar a los programadores a utilizar esta API para el código futuro. Creo que el punto más difícil sería la refacturación de todas las transacciones, ya que ya tenemos un gran código base. No estoy seguro si eso valdría la pena el tiempo involucrado. Pensando en ello ... –

0

No conozco ningún complemento R # existente que compruebe esto, pero ciertamente podría crear uno propio. Todo lo que tendría que hacer es detectar una instrucción using con una declaración de variable del tipo TransactionScope, luego iterar las instrucciones contenidas buscando la llamada Complete().

Si usted está interesado en hacer esto, le recomiendo que descargue el ReSharper SDK y revise el Plugin Development Guide.

Cuestiones relacionadas