views:

114

answers:

4

The project that I'm working on at the moment uses an IDisposable object in every method in a class. It has started getting tedious re-typing the using block at the start of every method, and was wondering if there was a way to specify a disposable variable for use in every method of the class?

public static class ResourceItemRepository
{
    public static ResourceItem GetById(int id)
    {
        using (var db = DataContextFactory.Create<TestDataContext>())
        {
            // Code goes here...
        }
    }
    public static List<ResourceItem> GetInCateogry(int catId)
    {
        using (var db = DataContextFactory.Create<TestDataContext>())
        {
            // Code goes here...
        }
    }
    public static ResourceItem.Type GetType(int id)
    {
        using (var db = DataContextFactory.Create<TestDataContext>())
        {
            // Code goes here...
        }
    }
}
+10  A: 

No, there's nothing particularly geared towards this. You could write:

public static ResourceItem GetById(int id)
{
    WithDataContext(db =>
    {
        // Code goes here...
    });
}

// Other methods here, all using WithDataContext

// Now the only method with a using statement:
private static T WithDataContext<T>(Func<TestDataContext, T> function)
{
    using (var db = DataContextFactory.Create<TestDataContext>())
    {
        return function(db);
    }
}

I'm not sure that it would be particularly beneficial though.

(Note that I've had to change it from Action<TestDataContext> in my original version to Func<TestDataContext, T> as you want to be able to return values from your methods.)

Jon Skeet
I have learned something from your reply - have been trying to get my head around lambda expressions and using them in the real world. Thanks.
Greg
@Downvoter: Care to give a reason?
Jon Skeet
Nice solution... Only question would be how to make it easier to unit test... I've used IOC to inject the context factory, so I guess I answered my own question...
Bryce Fischer
+1  A: 
private delegate void ContextAction(TestDataContext context);

private static void PerformAction(ContextAction contextAction)
{
        using (var db = DataContextFactory.Create<TestDataContext>()) 
        { 
            contextAction(db);
        } 
}
vc 74
I can't understand how this means I don't need to type out using blocks for each method?
Greg
@Greg: this is the same solution as Jon's, except that instead of using one of the stock delegate types (`Action` or `Func`) vc used a custom delegate type (`ContextAction`).
Martinho Fernandes
@Greg, sorry, I did not include the calling part: if you implement the previous, you can write (for instance): public static ResourceItem GetById(int id) {PerformAction((contextAction) => //Code here to retrieve by id;} You can rely on Mr Skeet's answer
vc 74
+3  A: 

Frankly, i'd keep the verbose code, but using a snippet instead of typing it all each time. Either create your own snippet with a special tool or use text-replacement tools like Texter

samy
A: 

Maybe a simple refactoring is the best that you can do without resorting to something like PostSharp:

public static class ResourceItemRepository {
  public static ResourceItem GetById(int id) {
    using (var db = CreateDataContext()) {
      // Code goes here... 
    }
  }
  public static List<ResourceItem> GetInCateogry(int catId) {
    using (var db = CreateDataContext()) {
      // Code goes here... 
    }
  }
  public static ResourceItem.Type GetType(int id) {
    using (var db = CreateDataContext()) {
      // Code goes here... 
    }
  }
  private static TestDataContext CreateDataContext() {
    return DataContextFactory.Create<TestDataContext>();
  }
}
Jordão