简体   繁体   中英

Are objects from an implementation factory method disposed by the DI container .Net Core

When I register an implementation of an interface with an explicit implementationFactory, like this:

services.AddTransient<IDbConnection>(_ => new SqlConnection(connectionString));

The implementation is initialized when requested and disposed when out of scope by the DI container.

But will the SqlConnection also be disposed by the DI container when I do something like this:

services.AddTransient<IRepository>(_ => new Repository(new SqlConnection(connectionString)));

The intellisense isn't warning me about the undisposed object that implements IDisposable, but I don't think that's right.

No, container will not dispose in second case, because it does not know anything about this manually created instance:

class MyDisposable : IDisposable
{
    public bool Disposed { get; private set; }
    public void Dispose()
    {
        Disposed = true;
    }
}

class Container
{
    public Container(MyDisposable d)
    {
        Disposable = d;
    }
    public MyDisposable Disposable { get; private set; }
}

var col = new ServiceCollection();
col.AddTransient<MyDisposable>(_ => new MyDisposable());
col.AddTransient<Container>(s => new Container(new MyDisposable()));

Container container;
MyDisposable disposable;
using(var scope = col.BuildServiceProvider().CreateScope())
{
    container = scope.ServiceProvider.GetRequiredService<Container>();
    disposable = scope.ServiceProvider.GetRequiredService<MyDisposable>();
}
Console.WriteLine(disposable.Disposed); // true
Console.WriteLine(container.Disposable.Disposed); // false

But if you change second registration to:

col.AddTransient<Container>(s => new Container(s.GetRequiredService<MyDisposable>()));

both MyDisposable 's will be disposed.

Using [Autofac][1] , for example you can resolve current lifetime scope and schedule manually created instance for disposal when this scope ends:

var builder = new ContainerBuilder();
builder.Register(_ => new MyDisposable()).InstancePerDependency();
builder.Register(ctx => 
{
    var scope = ctx.Resolve<ILifetimeScope>();
    var dep = new MyDisposable();
    scope.Disposer.AddInstanceForDisposal(dep);
    return new Container(dep);
})
.InstancePerDependency();

Container container;
MyDisposable disposable;
using(var scope = builder.Build().BeginLifetimeScope())
{
    container = scope.Resolve<Container>();
    disposable = scope.Resolve<MyDisposable>();
}

Console.WriteLine(disposable.Disposed); // true
Console.WriteLine(container.Disposable.Disposed);  // true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM