Code Snippet: Adding Dispose without IDisposable

Written by Troy Howard

11 November 2010

The topic of implementing IDisposable within Lucene.Net comes up a lot. While I'm all for it, there are reasons why it hasn't be done yet.

This is an alternative technique that allows using Dispose without implementing IDisposable directly.

This example uses a wrapper class, which does implement IDisposable, and allows the user to inject a custom action to happen when Dispose is called. It's a bit more fragile than directly implementing IDisposable but can be effective if done correctly.

using System;
using Lucene.Net.Index;

namespace Lucene.Net.Extensions
{
    public class Disposable<T> : IDisposable
    {
        public Disposable() { }
        public Disposable(T entity, Action<T> disposeAction)
        {
            Entity = entity;
            DisposeAction = disposeAction;
        }

        public T Entity { get; set; }
        public Action<T> DisposeAction { get; set; }

        public void Dispose()
        {
            if (default(Action<T>) != DisposeAction)
                DisposeAction(Entity);
        }

    }

    public static class DisposableExtensions
    {
        public static Disposable<T> AsDisposable<T>(this T entity, Action<T> disposeAction)
        {
            return new Disposable<T>(entity, disposeAction);
        }
    }

    public class LuceneDisposableExample
    {
        public void Example()
        {
            string pathToIndex = @"C:\lucene\example\index";

            using (var disposableReader = IndexReader.Open(pathToIndex, true).AsDisposable(a => a.Close()))
            {
                var reader = disposableReader.Entity;

                // .. whatever you want here... 
            }
        }
    }
}

This is available as a Gist here: https://gist.github.com/thoward/673545