What do you get when you marry the IDisposable interface to the Action delegate? Disposable Actions... with a bit of syntactic sugar. As you may or may not know, you can use the using block on types that implement the IDisposable interface. When the block is exiting it will call dispose on the type. For example the following block of code uses the "using" block.

public void DemoWithUsingBlock()
  {
      using (MemoryStream stream = new MemoryStream()) 
      {
          // do something with the stream
      }
  }

But when compiled, the above block of code actually expands out to something like…

public void DemoOfUsingBlockExpanded()
  {
      MemoryStream stream = null;
      try 
      {
          stream = new MemoryStream();
          // do something with the stream
      }
      finally 
      {
          if (stream != null) stream.Dispose();
      }
  }

Ok, so now let’s take a look at the signature for the Action delegate.

public delegate void Action<T>(T obj);

The signature returns void and takes in an object of type T. Quite simple actually. I’m sure you can think of quite a few methods that match that signature, but just in case you can’t here are a couple of examples.

public void DemoAction()
  {
      Do<string>(Console.Out.WriteLine);
      Do<Type>(MyMethodThatMatchesTheActionDelegateSignature);
  }

  public void Do<T>(Action<T> action)
  {
  }

  private void MyMethodThatMatchesTheActionDelegateSignature(Type type)
  {
  }

Ok, hopefully that makes sense! Now on to the good stuff. Suppose we created a type that implemented the IDisposable interface, and took in our closing action. This action would run when a process is completed. In this scenario the “Dispose” method is not being used to clean up resources, but rather to signal the end of a running process. For instance suppose we wanted to write a message to the console upon completion of a long running process.

using (new DisposableConsoleLogger("Finished running...")) 
  {
      // do something
  }

The above code uses the “using” block to wrap a sequence of events to call an action when the sequence of events is completed. When the “do something” block of code is completed the “Finished running…” message will be spit out to the console. The underlying implementation looks like this…

public class DisposableAction<T> : IDisposableAction 
  {
      public DisposableAction(Action<T> _action, T _itemToActOn) 
      {
          this._action = _action;
          this._itemToActOn = _itemToActOn;
      }

      public void Dispose() 
      {
          _action(_itemToActOn);
      }

      private Action<T> _action;
      private T _itemToActOn;
  }

  public class DisposableConsoleLogger : DisposableAction<string> 
  {
      public DisposableConsoleLogger(string completionMessage) : base(Console.Out.WriteLine, completionMessage){}
      public DisposableConsoleLogger() : base(Console.Out.WriteLine, "completed action"){}
  }

Perhaps the following block of code might make a little more sense to you now…

using (mockery.Record()) 
  {
      // ReplayAll()
  }
  using (mockery.Playback()) 
  {
      // VerifyAll()
  }

Source Code (1.94 KB)

comments powered by Disqus