So far we've kind of assumed for most of the time that the ImportantObject is easy to create. If not you probably want to create an interface for the ImportantObject. And creating an interface is probably a good idea anyway. So this is a refactoring of all code we have from yesterday.

1: public interface ImportantInterface 2: { 3: void ImportantMethod(); 4: } 5:   6: public class ImportantObject : ImportantInterface 7: { 8: public void ImportantMethod() 9: { 10: // Do things. 11: } 12: } 13:   14: public interface Lock 15: { 16: void Lock(); 17: void Unlock(); 18: } 19:   20: public class MutexLock : Lock 21: { 22: private readonly Mutex _lock = new Mutex(); 23:   24: public void Lock() 25: { 26: _lock.WaitOne(); 27: } 28:   29: public void Unlock() 30: { 31: _lock.ReleaseMutex(); 32: } 33: } 34:   35: public class Transaction : IDisposable 36: { 37: private readonly Lock _lock; 38: public ImportantInterface ImportantObject { get; private set; } 39:   40: public Transaction(ImportantInterface importantObject, Lock aLock) 41: { 42: ImportantObject = importantObject; 43: _lock = aLock; 44: _lock.Lock(); 45: } 46:   47: public void Dispose() 48: { 49: _lock.Unlock(); 50: } 51: } 52:   53: class FakeLock : Lock 54: { 55: public bool IsLocked { get; private set; } 56:   57: public FakeLock() 58: { 59: IsLocked = false; 60: } 61:   62: public void Lock() 63: { 64: IsLocked = true; 65: } 66:   67: public void Unlock() 68: { 69: IsLocked = false; 70: } 71: } 72:   73: class DummyObject : ImportantInterface 74: { 75: public void ImportantMethod() 76: { 77: Assert.True(false, "Dummy should never be used"); 78: } 79: } 80:   81: public class When_using_a_transaction 82: { 83: private FakeLock _lock; 84:   85: public When_using_a_transaction() 86: { 87: _lock = new FakeLock(); 88: } 89:   90: [Fact] 91: void It_should_take_lock_when_created() 92: { 93: Assert.False(_lock.IsLocked); 94: using (Transaction transaction = new Transaction(new ImportantObject(), _lock)) 95: { 96: Assert.True(_lock.IsLocked); 97: } 98: } 99:   100: [Fact] 101: void It_should_release_lock_when_leaving_scope() 102: { 103: using (Transaction transaction = new Transaction(new ImportantObject(), _lock)) 104: { 105: Assert.True(_lock.IsLocked); 106: } 107: Assert.False(_lock.IsLocked); 108: } 109: } 110:   111: public class Given_a_transaction 112: { 113: private Transaction _transaction = new Transaction(new DummyObject(), new FakeLock()); 114:   115: [Fact] 116: void It_should_return_an_ImportantObject() 117: { 118: Assert.NotNull(_transaction.ImportantObject); 119: } 120: }