MarcBalta
MarcBalta

Reputation: 131

AutoFac Delegate Factories and the Lifetime Scope

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

Answers (2)

Erkan Demirel
Erkan Demirel

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

MaKCbIMKo
MaKCbIMKo

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 Componentand then (once LifetimeScopeis ended) calls Disposeon 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

Related Questions