3

I'd like to use LightInject's constructor injection feature, but I'd like to clear up things first about lifetime management of IDisposables.

Consider the following:

Example A

public class Foo : IDisposable
{
    readonly IBar bar;
    public Foo(IBar bar)
    {
        this.bar = bar;
    }

    public void Dispose()
    {

    }
}

Example B

 public class Foo : IDisposable
 {
    readonly IBar bar;
    public Foo(Func<string, IBar> bar)
    {
        this.bar = bar("myParameter");
    }

    public void Dispose()
    {

    }
 }

My questions for both examples:

  1. Will Dispose method be called by LightInject on IBar after Foo is disposed or should I call dispose myself?
  2. If IBar is using a PerContainerLifeTime, will Dispose be called after every Foo instance disposed?

Edit Well the 2nd question is stupid I realize, a PerContainerLifeTime instance is of course disposed when the container is Disposed. My overall question would be, is LightInject tracking injected dependencies, and dispose them itself?

uzul
  • 1,096
  • 9
  • 23

1 Answers1

2

LightInject will only track instances it creates if the service/dependency is registered with the PerScopeLifetime or the PerRequestLifetime. Take a look at the following example:

class Program
{
    private static IServiceContainer container = new ServiceContainer();

    static void Main(string[] args)
    {
        container.Register(f => new Foo("PerScopeFoo"), "PerScopeFoo", new PerScopeLifetime());
        container.Register(f => new Foo("PerRequestFoo"), "PerRequestFoo", new PerRequestLifeTime());
        container.Register(f => new Foo("PerContainerFoo"), "PerContainerFoo", new PerScopeLifetime());
        container.Register(f => new Foo("TransientFoo"), "TransientFoo");

        using (container.BeginScope())
        {
            var first = container.GetInstance<Foo>("PerScopeFoo");
            var second = container.GetInstance<Foo>("PerScopeFoo");
            Debug.Assert(first == second);

            first = container.GetInstance<Foo>("PerRequestFoo");
            second = container.GetInstance<Foo>("PerRequestFoo");

            Debug.Assert(first != second);

            first = container.GetInstance<Foo>("PerContainerFoo");
            second = container.GetInstance<Foo>("PerContainerFoo");

            Debug.Assert(first == second);

            first = container.GetInstance<Foo>("TransientFoo");
            second = container.GetInstance<Foo>("TransientFoo");

            Debug.Assert(first != second);
        }

        container.Dispose();

        Console.ReadKey();
    }        
}

public class Foo : IDisposable
{
    private readonly string name;

    public Foo(string name)
    {
        this.name = name;
    }

    public void Dispose()
    {
        Console.WriteLine(name + " disposed");
    }
}
seesharper
  • 3,249
  • 1
  • 19
  • 23
  • Thank you for your answer :) So, would this mean that a PerScope instance is disposed when the scope is disposed, and that a PerRequest instance is disposed when it's not referenced anymore? (internally by using a WeakReference?) – uzul Apr 04 '15 at 16:24
  • No, it means that a PerRequest instance is disposed when the scope ends or when the scope is disposed to be exact :) – seesharper Apr 07 '15 at 07:04
  • if I'm not using scopes, would this mean there will be a memory leak using PerRequest? if so I'll have to use scopes. (especially the async version). Also I felt the need of a "CacheLifeTime", that returns the same instance until timeout. Is there anything implementing something like that? – uzul Apr 10 '15 at 12:34
  • As a general rule, you should always make sure that objects implementing IDisposable gets explicitly disposed. The very fact that they implement IDisposable is usually an indication that they hold on to resources that need to be released explicitly. LightInject manages disposal of such objects with the use of scopes. As for the CacheLifetime, you are free to implement the ILifetime interface and thus creating whatever lifetime you want – seesharper Apr 13 '15 at 11:00
  • @seesharper will LightInject.Mvc hook into the Mvc pipeline and automatically create a scope at the start of a http request and dispose the scope at the end of the http request? – Chris Marisic Apr 13 '15 at 15:41
  • In the context of a web application, the scope starts when the web request starts and ends when the web request ends – seesharper Apr 14 '15 at 13:56
  • There seems to be a bug with PerScopeLifetime registered objects not getting disposed unless something holds a reference to it. – Michael Brown May 04 '20 at 23:10