33

So, I have a method exposed from a WCF service as such:

public GetAllCommentsResponse GetAllComments(GetAllCommentsRequest request)
{
    var response = new GetAllCommentsResponse();

    using(_unitOfWork)
        try
        {
            Guard.ArgNotNull(request, "request");

            var results = _unitOfWork.CommentRepository.Get(d => d.Id > 0).ToArray();

            //... Do rest of stuff here
        }
        catch (Exception ex)
        {
            response.Success = false;
            response.FailureInformation = ex.Message;
            Logger.LogError("GetAllComments Method Failed", ex);
        }

    return response;
}

I have a global DataUnitOfWork object (which implements IDisposable) that gets instantiated by Ninject through a constructor argument when a service call comes in. When debugging, if I use

using(_unitOfWork)

the _unitOfWork object gets disposed immediately after going out of scope then gets called again by Ninject (although it's been marked as disposed, so nothing happens.) Without the using statement, Ninject handles the disposing.

Long story short, is there a general rule of thumb for this? I've been scared of the whole IDisposable thing after everything I read seems to indicate never to use it, or use it in certain eclectic situations, but it's always confused me.

Any input is appreciated.

Oh, also while I'm here typing anyway, why exactly is there a call to GC.SuppressFinalize() when disposing? How do Dispose and Finalize differ?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Nate222
  • 856
  • 2
  • 15
  • 25
  • Found answer in similar post: http://stackoverflow.com/questions/898828/c-sharp-finalize-dispose-pattern – Nate222 Apr 19 '12 at 23:04
  • The `SuppressFinalize` tells the GC system 'Don't worry about calling `Finalize` when you've determined the object is garbage as we've already performed the cleanup thanks to someone explicityl calling `Dispose` on it. If you don't do this, the object remains on the finalizer queue and Dispose _will_ get called again from the Finalizer thread. – Ruben Bartelink Apr 20 '12 at 19:49

1 Answers1

54

The CLR documentation states that whoever creates a Disposable object is responsible for calling Dispose. In this case the object is created by Ninject. That means you should not call Dispose explicitly.

Ninject disposes every Disposable object that has another scope other than InTransientScope as soon as the scope object to which the created object is tied is collected by GC. That's why every Disposable object should be Bindd with a scope that is not InTransientScope(). E.g. you can use InParentScope() from the NamedScope extension which will Dispose the object as soon as the object it is injected into is garbage collected.

Luke Hutton
  • 10,612
  • 6
  • 33
  • 58
Remo Gloor
  • 32,665
  • 4
  • 68
  • 98
  • 2
    Which means that in InRequestScope's `IDisposable` objects will be disposed at the end of the request? – AgentFire Aug 21 '12 at 06:55
  • Yes, assuming you've done everything right, including using the OncePerWebRequest module – Adam Tegen Dec 12 '12 at 19:08
  • As far as I can tell ninject never disposes InSingletonScope either. – trampster Dec 07 '15 at 22:11
  • 4
    InSingletonScope is Disposed when the Kernel is Disposed. https://github.com/ninject/ninject/wiki/Object-Scopes This should work: using(IKernel kernel = new StandardKernel()) { .... } – zidik Sep 15 '17 at 10:08
  • 2
    worth noting that "InTransientScope" is the default scope when none is provided: https://github.com/ninject/Ninject/wiki/Object-Scopes – Sharpiro Jul 08 '19 at 14:43