Are objects that are referenced, not created, within a factory implementation disposed by the container? See code below:
services.AddTransient(c => OwinContext.ServiceObject);
Will ServiceObject
, which implements IDisposable
, be disposed by the container considering it isn't created (i.e. new ServiceObject
)?
ServiceObject
is currently registered as Scoped, but we are getting ObjectDisposedException
on the rare occasion. I'm guessing it's getting disposed within OWIN sometimes before our services are able to use it, which is why I was hoping of making it Transient but I'm worried the container will dispose of it more frequently.
Disposable transient registrations are tracked by the container and disposed when their scope ends.
The Microsoft documentation is not always clear about this, as this documentation seems to suggest that "The framework does not dispose of the services automatically" that are "not created by the service container." Although the documentation is not incorrect, as it primarily talks about the registration of instances through the
AddSingleton<T>(T instance)
extension method — it is misleading because it doesn't hold for:AddSingleton<T>(Func<IServiceProvider, T>)
,AddScoped<T>(Func<IServiceProvider, T>)
, andAddTransient<T>(Func<IServiceProvider, T>)
.This statement can be easily verified using the following program:
Output:
Conclusion: Yes, transient registrations for disposable objects are disposed of by the container.
There will be little difference between making this registration Transient or Scoped. In both cases the object will get disposed when the scope ends.
In the case of a Transient registration, though, you'll start to see the disposable get disposed of multiple times in case it gets injected multiple times. For instance:
Output:
From reliability, however, it's better to stick with a Scoped registration, instead of Transient. This is because MS.DI will prevent Scoped registrations from being injected into Singleton consumers (in case the Service Provider is created by calling
BuildServiceProvider(validateScopes: true)
). In case yourServiceContext
would get injected into a Singleton, it causes it to become a Captive Dependency and keep referenced (and likely used) by that Singleton, long after it got disposed of.The most likely reason you are getting those
ObjectDisposedException
s is because Owin tries to use theServiceContext
after your (web request) scope is disposed.The
ServiceContext
object is likely being controlled and disposed of by OWIN, which doesn't make it a good candidate to be disposed of by the container. But here's the problem: MS.DI will always try to dispose of Transient and Scoped registrations and the only way to prevent this from happening is to not register yourServiceContext
.The solution, therefore, is to wrap it in a "provider" object of some sort. For instance: