문제

Programmers on my team sometimes open a transaction and forget to include the scope.Complete() statement (see code block below). Any ideas on ways to either

(1) search our solution for missing scope.Complete() statements, or

(2) have Visual Studio automatically highlight or raise a warning for missing scope.Complete() statements?

Here's the line we miss:

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

What I have tried
 
I have tried using a ReSharper Custom Pattern for this purpose, with no luck. Ideally I would search for something like:

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

However, ReSharper only accepts regular expressions for identifiers, not for statements, so this does not appear to work (http://www.jetbrains.com/resharper/webhelp/Reference__Search_with_Pattern.html).

Any ideas? I'm open to using other plugins or tools as well.

Thanks,
Ben

도움이 되었습니까?

해결책

NDepend can certainly help, but cannot check 100% of what you are asking for. NDepend doesn't know about the method body internals (order of method calls). So at best, you can write a code rule over LINQ (CQLinq) that will check that if a method is creating a TransactionScope, at least it must call TransactionScope.Complete():

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

Note that if developers are disciplined enough to avoid creating multiple TransactionScope in one method, this rule should work for you.

다른 팁

Could you force programmers to use a custom API instead of the low-level scope.Complete stuff?

A closure will force usage of .Complete():

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

Then you could do:

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

I'm not aware of any existing R# plugin that checks for this, but you could certainly create one of your own. All you'd have to do is to detect a using statement with a variable declaration of the TransactionScope type, then iterate the contained statements looking for the Complete() call.

If you are interested in doing this, I recommend you download the ReSharper SDK and check out the Plugin Development Guide.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top