Reputation: 131
I'm using delegate Factories in my application. Thats because the components I create with AutoFac use Service classes that need some Parameter.
The next Thing I wanted to do is caring that these services are cleaned up correctly and resources are released using AutoFacs lifetime scope mechanism. The Problem however is that when I create the components using the delegate factories they seem not to be put into the lifetime scope and Dispose is not called after disposing the lifetime scope.
I want to avoid the generic Owned<> because I dont want to bind my application to a specific IOC.
In http://nblumhardt.com/2011/01/an-autofac-lifetime-primer/ it is explained that the created components by a delegate factory are put into the same lifetime scope as the delegate factory.
I wrote a small Programm to demonstrate this. In this Program I would expect that the Dispose function is called. Unfortunatley this doesnt happen. Do I miss here sth? Anything wrong with the code below? How can I assure that components produced by the delegate factory are put into the life time scope of the delegate factory?
using Autofac;
using Autofac.Core;
using System;
namespace FactoryTest
{
class Component : IDisposable
{
public Component(int i) { }
public void Dispose()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.Register<Func<int, Component>>(c => (x) =>
{
// code that is important and that should run
// inside the delegate factory.
return new Component(x);
});
IContainer root = builder.Build();
using (ILifetimeScope lf = root.BeginLifetimeScope())
{
Func<int, Component> compDelegatefac = lf.Resolve<Func<int, Component>>();
Component cmp = compDelegatefac(2);
}
}
}
}
Upvotes: 5
Views: 2083
Reputation: 4382
Edit: If you don't want to use Auto Generated Factories you can follow Delegate Factories
namespace FactoryTest
{
class Component : IDisposable
{
public delegate Component Factory(int i);
public Component(int i) { Console.WriteLine(i); }
public void Dispose()
{
Console.WriteLine("Component disposed");
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Component>().AsSelf();
IContainer root = builder.Build();
using (ILifetimeScope lf = root.BeginLifetimeScope())
{
var compDelegatefac = lf.Resolve<Component.Factory>();
Component cmp = compDelegatefac(2);
}
GC.Collect();
Console.Read();
}
}
}
Upvotes: 1
Reputation: 2820
In your example Lifetime Scope works well.
In your code you register a factory for delegate. It means that it will dispose an object of Func<int, Component>
, but not for your Component
(because it created by Func
, not by Autofac
).
Here is an example (Dispose is called):
void Main()
{
var builder = new ContainerBuilder();
builder.Register<Component>(c=>new Component(123));
IContainer root = builder.Build();
using (ILifetimeScope lf = root.BeginLifetimeScope())
{
var comp = lf.Resolve<Component>();
}
}
class Component : IDisposable
{
public Component(int i) { }
public void Dispose()
{
throw new NotImplementedException();
}
}
In this example it creates an instance of Component
and then (once LifetimeScope
is ended) calls Dispose
on it.
Edit:
void Main()
{
var builder = new ContainerBuilder();
builder.Register<Component>(c => new Component(123));
builder.RegisterType<ComponentUser>().AsSelf();
IContainer root = builder.Build();
using (ILifetimeScope lf = root.BeginLifetimeScope())
{
var comp = lf.Resolve<ComponentUser>();
}
}
class ComponentUser
{
Component Component { get; set;}
public ComponentUser(Func<Component> func)
{
Component = func();
}
}
class Component : IDisposable
{
public Component(int i) { }
public void Dispose()
{
throw new NotImplementedException();
}
}
That how it works.
Upvotes: 0