0

I am trying to implement the Execute Around pattern described in Kent Beck's Smalltalk Best Practice Patterns. An example in Java could be found here.

Basically, I am repeatedly opening and closing a pdf document while performing various operations, something like,

public void Parse()
{
    // Open the document
    PdfLoadedDocument loadedDocument = new PdfLoadedDocument("plan.pdf");

    List<string> annotations = Build(loadedDocument);

    // Close the document
    loadedDocument.Save();
    loadedDocument.Close();
}

I would like to move the opening and closing the document in a centralized place, as I have tens of similar methods. All these methods open the document, perform an action, and close the document, and it's easy to forget to close the document.

Here is what I tried:

public void BuildAnnotations()
{
    List<string> annotations = null;

    ExecuteAction("plan.pdf", (PdfLoadedDocument loadedDocument) =>
    {
        annotations = Build(loadedDocument);
    });
}

private void ExecuteAction(string path, Action<PdfLoadedDocument> perform)
{
    PdfLoadedDocument loadedDocument = new PdfLoadedDocument(path);

    try
    {
        perform(loadedDocument);
    }
    catch(Exception e)
    {
        Console.WriteLine($"An error occured. {e}");
    }

    loadedDocument.Save();
    loadedDocument.Close();
}

My question is, is passing a lambda to an Action delegate a good idea? I am not that familiar with delegates, Actions, and lambdas (other than using them in linq queries). Are there any other better alternatives?

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
software_writer
  • 3,941
  • 9
  • 38
  • 64
  • 1
    fwiw, the talk of any pattern like this makes my eyes glaze over and i sigh. secondly, the action parameter is fine, though why not just use a using statement. you could do other things of course too. However asking is there any better alternatives is a very sticky and subjective question. Better is relative. Here is the deal, if you like what you have, and you find it readable, and you think other people can read it, then you have your answer – TheGeneral May 05 '19 at 23:25
  • Thanks, I understand that it's not wise to implement patterns just for the sake of it. However, I think I have a valid case where using this pattern will simplify my code by centralizing the opening/closing of the file. Is there anything wrong with this? – software_writer May 05 '19 at 23:29

1 Answers1

2

Have you considered implementing IDisposable interface, so later you can use using keyword, e.g.:

using (PdfLoadedDocument loadedDocument = new PdfLoadedDocument(path))
{
    List<string> annotations = Build(loadedDocument);
}

public class PdfLoadedDocument : IDisposable
{
    public void Close()
    {

    }

    public void Save()
    {

    }

    public void Dispose()
    {
        Save();
        Close();
    }
}
Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125