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?