Denis535
Denis535

Reputation: 3590

How to make ServiceProvider to call Dispose on objects created manually?

I'm using Microsoft.Extensions.DependencyInjection (default implementation). I noticed that when I'm adding my object as singleton then ServiceProvider ignores IDisposable on my object.

var instance = new MyDisposableObj();
ServiceLocator.Instance = instance;

var services = new ServiceCollection();
services.AddSingleton( instance );
var container = services.BuildServiceProvider();
container.Dispose();

Looks like microsoft think that I have to manually dispose objects which are created manually.

But in the case when I do the extension for ServiceCollection I want to encapsulate disposing of my object. I shouldn't force the users of my extension to dispose my object manually!

So, is it possible to change this behavior?

Upvotes: 2

Views: 5870

Answers (2)

Adam Jachocki
Adam Jachocki

Reputation: 2125

There is another option, I think - more proper. Look at ServiceProvider. It implements IDisposable. It means that you should create ServiceProvider by using statement:

using(var provider = collection.BuildServiceProvider()) { var service1 = provider.GetRequiredService(); }

And that's all.

Upvotes: 1

arekf
arekf

Reputation: 61

I know this is old but maybe it will help to clarify a bit.
You can create object yourself and register using implementation factory. DI will take care of disposing object, as it is taking ownership of it by calling factory method.
It is described in msdn.

var instance = new MyDisposableObj();
var services = new ServiceCollection();
services.AddSingleton(x => instance);
var container = services.BuildServiceProvider();
container.Dispose();

You can verify this with simple unit test

[Fact]
public void ServiceProvider_SingletonObjectAddedAsFactory_IsDisposedWithContainer()
{
        // Arrange
        var sc = new ServiceCollection();
        var fake = A.Fake<IDisposable>();
        sc.AddSingleton(x => fake);

        // Act
        var sp = sc.BuildServiceProvider();
        var recieved = sp.GetService<IDisposable>();
        sp.Dispose();

        // Assert
        recieved.Should().NotBeNull();
        A.CallTo(() => fake.Dispose()).MustHaveHappenedOnceExactly();
}

Upvotes: 4

Related Questions