How to Reconcile Idisposable and Ioc

How do you reconcile IDisposable and IoC?

AutoFac handles this by allowing the creation of a nested container. When the container is finished with, it automatically disposes of all IDisposable objects within it. More here.

.. As you resolve services, Autofac tracks disposable (IDisposable) components that are resolved. At the end of the unit of work, you dispose of the associated lifetime scope and Autofac will automatically clean up/dispose of the resolved services.

IOC containers and IDisposable

Deriving an interface from IDisposable is in my opinion a design smell that indicates a Leaky Abstraction. As Nicholas Blumhardt put it:

an interface [...] generally shouldn't be disposable. There's no way for the one defining an interface to foresee all possible implementations of it - you can always come up with a disposable implementation of practically any interface.

Consider why you want to add IDisposable to your interface. It's probably because you have a particular implementation in mind. Hence, the implementation leaks into the abstraction.

An DI Container worth its salt should know when it creates an instance of a disposable type. When you subsequently ask the container to release an object graph, it should automatically dispose the disposable components (if their time is up according to their lifestyles).

I know that at least Castle Windsor and Autofac does this.

So in your case, you should keep your type like this:

class Foobar: IFoobar, IDisposable {};

You may find Nicholas Blumhardt's post The Relationship Zoo interesting as well - particularly the discussion about Owned<T>.

DI: Handling Life of IDisposable Objects

Maybe I'm missing something, but why add new methods to the API? When an object is added to the container, you could as-cast to check if it's IDisposable and handle it appropriately if so.

I'm also wondering if you need the destructor. Presuming the container is IDisposable (like Unity's), you could just implement the Basic Dispose Pattern and save a lot of GC overhead.

Some questions that may be applicable:

  • How do you reconcile IDisposable and IoC?
  • Can inversion of control and RAII play together?

ServiceContainer, IoC, and disposable objects

(Disclaimer: I'm answering this based on java stuff. Although I program C# I haven't proxied anything in C# but I know it's possible. Sorry about the java terminology)

You could let the IoC framework inspect the object being constructed to see if it supports
IDisposable. If not, you could use a dynamic proxy to wrap the actual object that the IoC framework provides to the client code. This dynamic proxy could implement IDisposable, so that you'd always deliver a IDisposable to the client. As long as you're working with interfaces that should be fairly simple ?

Then you'd just have the problem of communicating to the developer when the object is an IDisposable. I'm not really sure how this'd be done in a nice manner.

Autofac: How to limit the lifetime of an IDisposable object without passing around the IoC container

The other answers here are insightful, but have a problem. In both cases, if Apple has other dependencies that need disposal, correct cleanup won't happen.

Autofac 2 provides a new feature to help here, called "owned instances". I noticed that your registration code is Autofac 1.4, so if you're unable to upgrade let me know (there are other, less transparent, ways to do this.)

Register Apple as usual (not externally owned):

builder.RegisterType<Apple>().As<IApple>();

Declare AppleFactory as:

public delegate Owned<IApple> AppleFactory();

In Autofac 2, you do not need to call RegisterGeneratedFactory() anymore - this is automatic.

Then, in HorseKeeper, feed the horse like this:

public void FeedHorse()
{
using (var apple = appleFactory())
{
horse.Eat(apple.Value);
}
}

(Note the .Value property to get the underlying IApple.

At the end of the using block the apple, plus all of its dependencies, will be cleaned up.

Any other components that use IApple directly (as dependencies) will get the usual behaviour.

How do I manage object disposal when I use IoC?

From what I know (I did a research about a month ago) Ninject does not support lifecycle management at all. Castle Windsor and AutoFac (and to some extent StructureMap, but only when using nested containers) will take care of disposing disposable components they create at appropriate time.

Stack Overflow when Disposing a Managed Resource

This is implementation of IDisposable within UnityContainer. It is obvious that you cannot dispose your parent container. It will iterate through all registrations and dispose them if they are also IDisposable. Take a look:

protected virtual void Dispose(bool disposing) 
{
if (disposing)
{
if (lifetimeContainer != null)
{
lifetimeContainer.Dispose();
lifetimeContainer = null;

if (parent != null && parent.lifetimeContainer != null)
{
parent.lifetimeContainer.Remove(this);
}
}

extensions.OfType<IDisposable>().ForEach(ex => ex.Dispose());
extensions.Clear();
}
}

Can inversion of control and RAII play together?

For this very reason I've made my own IoC container which returns (in C#/.NET) disposable service wrappers, that when disposed of, will "do the right thing" in regards to the service.

Be it:

  • Do nothing, when:

    • The object does not implement IDisposable
    • Is not container-scoped (in which case the container will keep track of it and return the same object more than once, and when the container is disposed of, the object will be too)
    • It is not pooled
    • It is not singleton-scoped (same as container-scoped, but a hierarchy of containers will store the singleton-scoped service in the topmost container)
  • Dispose of the service (it has factory scope, and implements IDisposable)
  • Return it to the pool

This means that all code that uses my services is inside a using-block, but the intent is more clear, at least to me:

using (var service = container.Resolve<ISomeService>())
{
service.Instance.SomeMethod();
}

basically it says: resolve a service, call SomeMethod on the service instance, and then dispose of the service.

Since knowledge of whether to dispose of the service instance or not isn't available to the consumer, there was either the choice of just ignoring IDisposable implementations altogether, or to dispose of all services which implement IDisposable. Neither was a good solution to me. The third choice was to wrap the service instance in an object that knew what to do with the service once the wrapper was disposed of.

IDisposable interface confirmation

For the sake of completion I will answer my question as I already know it.

It was pretty helpfull to read the following link:
https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/

  • is Case 1 and Case 2 the expected behaviour of object disposal in Autofac? or it is a bug?

It is Autofac normal behaviour. Aufofac will hold a reference to any IDisposable instance created by it and for this reason the GC will not free that resource until the autofac container at that scope is released.
It is important to be aware of this because you might think that the Net framework is going to release those variables, as their scope in the code has ended.
In the other hand, It could be a good feature if Autofac would be able to notice if it is the only one holding a reference to an instance and release it.

  • Is there a way to tell the container to free resources without disposing it? or a specific instance created by it?

There is no way to force releasing of a specific instance created by the container.
The only available option availabe is to follow the recomendation, use BeginLifeTimeScope before any container resolve invocation and hold somehow a reference to the lifetime scope to release it when needed.

This could be also a good feature though.

Thanks for the answers and sorry if some part of the text was not straight forward.

How to make an IDisposable object a class variable?

The general pattern for this is to implement the IDisposable interface on your class. Take this example:

public class YourClass : IDisposable
{
private OtherDisposableType yourResource;

public YourClass()
{
yourResource = new OtherDisposableType();
}

public void Dispose()
{
yourResource.Dispose();
}
}

This is, at a minimum, what you need to do.

EDIT

My previous version advocated following the finalizer pattern in all cases, which was (correctly) pointed out to be against the framework design guidelines. However, in the event that you're actually dealing with unmanaged resources (for example, you're making direct P/Invoke calls and obtaining a handle that needs to be explicitly freed) it's advisable that you create a finalizer and call Dispose within it to protect against people who consume your code and don't call Dispose:

public class YourClass : IDisposable
{
private OtherDisposableType yourResource;

public YourClass()
{
yourResource = new OtherDisposableType();
}

public void Dispose()
{
yourResource.Dispose();

GC.SuppressFinalize(this);
}

~YourClass()
{
Dispose();
}
}


Related Topics



Leave a reply



Submit