Autofac: How to limit the lifetime of an IDisposable object without passing around the IoC container
autofac, c#, dispose, idisposable, inversion-of-control
Solution
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.
Problem
I'm currently learning how to use Autofac, and I'm stuck with disposing `IDisposable` objects deterministically. Let me first present the situation before I'll state my problem. Starting position: Let's say my object model is defined through the following interfaces: ``` interface IApple : IDisposable { void Consume(); } interface IHorse { void Eat(IApple apple); // is supposed to call apple.Consume() } interface IHorseKeeper { void FeedHorse(); // is supposed to call horse.Eat(apple) // where 'horse' is injected into IHorseKeeper // and 'apple' is generated by IHorseKeeper on-the-fly } ``` Further, I define a delegate that will be used as an `IApple` factory: ``` delegate IApple AppleFactory; ``` Autofac configuration: Now, I would register the above types as follows -- note that I'm omitting the code of both classes `Apple` and `Horse`, since they're trivial to implement: ``` var builder = new Autofac.ContainerBuilder(); builder.RegisterType<Apple>().As<IApple>(); builder.RegisterType<Horse>().As<IHorse>(); builder.RegisterType<HorseKeeper>().As<IHorseKeeper>(); builder.RegisterGeneratedFactory<AppleFactory>(); ``` My problem: I don't quite know how to implement method `IHorseKeeper.Feed`. Here's what I currently have: ``` class HorseKeeper : IHorseKeeper { private readonly IHorse horse; private readonly AppleFactory appleFactory; public HorseKeeper(IHorse horse, AppleFactory appleFactory) // ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ // constructor injection { this.horse = horse; this.appleFactory = appleFactory; } public void FeedHorse() { using (var apple = appleFactory()) { horse.Eat(apple); } // <- Dispose() apple now (ASAP), as it's no longer needed! } } ``` This is the kind of code I would like to have, as it's completely Autofac-agnostic. It could just as well work with another IoC container, as long as `AppleFactory` works as expected. However, because Autofac handles the `AppleFactory` for me, it will keep track of all `IApple` objects it produces for me, and will therefore want to `Dispose` them itself at the end of the container's lifetime. Ie., the produced `apple` will be disposed twice. I suppose registering `IApple` as `.ExternallyOwned()` is no viable solution, as there might be cases where it's easier to let Autofac handle the `IApple`s' lifetime. Deterministic disposal with Autofac requires the creation of a nested container using `container.BeginLifetimeScope()`, however I don't want to use this inside `HorseKeeper.FeedHorse` because then `HorseKeeper` becomes dependent on Autofac, and I would like to keep my code IoC-agnostic. Question: How do I implement `HorseKeeper.FeedHorse` in a IoC (Autofac)-agnostic way while ensuring that on-the-fly generated objects are disposed properly?