IAsyncDisposable is coming to in C# 8 https://github.com/dotnet/corefx/issues/32640. We need to figure out what happens when services implement IAsyncDisposable. We need to figure out what to prefer if both are on a type and we also need to implement the interface on the ServiceProvider type.
And on IServiceScope. It would be a breaking change but a lot of containers would need to add support for IAsyncDisposables so maybe coordinated breaking change is fine.
@davidfowl @pakrym CoreFX change seems done. Do we expect we'll do this in 3.0?
This needs design. Would be nice to have a general idea for 3.0.
@davidfowl @pakrym I was thinking a bit about this today and I was glad to see the issue already exists. Any further thinking has happened?
Re preference, I was thinking that if a type implements both IDisposable and IAsyncDisposable, DI should give priority to call DisposeAsync, because it is likely to contain the non-blocking version of the same logic as Dispose. Once DiposeAsync executes once, assuming the guidance is still that subsequent calls do Dispose (or DisposeAsync) no-op, there shouldn't be a problem (but also no gain) in calling Dispose later on.
I assume that the aspects that need the most design are:
We need to implement IAsyncDisposable in the DI interfaces as well, e.g. IServiceScope (which @pakrym already mentioned) and we need new async code paths in other places (ASP.NET Core) to start calling into it.
If Microsoft.Extensions.* packages still need to (multi)target .NET Standard 2.0, how do we handle the fact that the interface doesn't exist, at least in some version of the types?
Wouldn't it be better to add a new interface that represents a service scope that is async-disposable? That way existing providers (or providers that are .NET Standard 2.0 only) are not forced to support this, and we also are able to tell whether we are dealing with a provider that has support.
On the other hand, if a service only implements IAsyncDisposable and not IDisposable, and we know we are dealing with a DI provider that doesn't support IAsyncDisposable, do we get a chance to throw?
I think we'll start with "soft" implementation by implementing IAsyncDisposable on ServiceProvider and ServiceProviderEngineScope but without adding it to IServiceScope interface. This would allow both of them to be cast to IAsyncDisposable without making major breaking changes.
If Microsoft.Extensions.* packages still need to (multi)target .NET Standard 2.0, how do we handle the fact that the interface doesn't exist, at least in some version of the types?
Conditionally remove the implementation out of netstandard library.
On the other hand, if a service only implements IAsyncDisposable and not IDisposable, and we know we are dealing with a DI provider that doesn't support IAsyncDisposable, do we get a chance to throw?
IAsyncDisposable inherits from IDisposable so this shouldn't be a problem.
Most helpful comment
I think we'll start with "soft" implementation by implementing IAsyncDisposable on
ServiceProviderandServiceProviderEngineScopebut without adding it toIServiceScopeinterface. This would allow both of them to be cast toIAsyncDisposablewithout making major breaking changes.Conditionally remove the implementation out of netstandard library.
IAsyncDisposable inherits from IDisposable so this shouldn't be a problem.