Skip to content

Issue with disposable singletons #15

Closed
@peter-perot

Description

@peter-perot

Let's assume we have the following types:

public interface IMyInterface
{
}

public sealed class MyClass : IMyInterface, IDisposable
{
  public void Dispose()
  {
    Console.WriteLine("Disposing");
  }
}

When using Microsoft ASP.NET DependencyInjection the following code works correctly:

private static void MicrosoftDI_1()
{
  var sc = new ServiceCollection();
  var externallyOwned = new MyClass();

  sc.AddSingleton<IMyInterface>(externallyOwned);

  var sp = sc.BuildServiceProvider();

  var myObj = sp.GetRequiredService<IMyInterface>();

  ((IDisposable)sp).Dispose(); // myObj is _not_ disposed
}

The externally owned singleton is not disposed - that's correct.

The following code works correctly, too:

private static void MicrosoftDI_2()
{
  var sc = new ServiceCollection();

  sc.AddSingleton<IMyInterface>(_ => new MyClass());

  var sp = sc.BuildServiceProvider();

  var myObj = sp.GetRequiredService<IMyInterface>();

  ((IDisposable)sp).Dispose(); // myObj is disposed
}

Here the singleton myObj is disposed, because it is created inside of a lamdba factory function -
correct so far.

Now let's see what Autofac using the Microsoft ASP.NET DependencyInjection adapter is doing:

private static void AutofacDI_1()
{
  var sc = new ServiceCollection();
  var externallyOwned = new MyClass();

  sc.AddSingleton<IMyInterface>(externallyOwned);

  var cb = new ContainerBuilder();
  cb.Populate(sc);
  var ctnr = cb.Build();
  var sp = new AutofacServiceProvider(ctnr);

  var myObj = sp.GetRequiredService<IMyInterface>();

  ctnr.Dispose(); // myObj is disposed - this is not correct!
}

The externally owned singleton is disposed on container disposal - this is not correct.

When using a lambda factory function, Autofac is working correctly:

private static void AutofacDI_2()
{
  var sc = new ServiceCollection();

  sc.AddSingleton<IMyInterface>(_ => new MyClass());

  var cb = new ContainerBuilder();
  cb.Populate(sc);
  var ctnr = cb.Build();
  var sp = new AutofacServiceProvider(ctnr);

  var myObj = sp.GetRequiredService<IMyInterface>();

  ctnr.Dispose(); // myObj is disposed
}

The singleton is disposed as expected.

Used versions:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Autofac" version="4.6.0" targetFramework="net46" />
  <package id="Autofac.Extensions.DependencyInjection" version="4.1.0" targetFramework="net46" />
  <package id="Microsoft.Extensions.DependencyInjection" version="1.1.1" targetFramework="net46" />
  <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.1" targetFramework="net46" />
</packages>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions