New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow created disposable instances to be retrieved from their Scope #478

Closed
dotnetjunkie opened this Issue Oct 24, 2017 · 1 comment

Comments

1 participant
@dotnetjunkie
Collaborator

dotnetjunkie commented Oct 24, 2017

A SimpleInjector.Scope instance maintains an internal cache for the scoped instances creates. There however is currently no possibility to retrieve this list of created instances from the Scope for further processing.

A Scope.GetCreatedInstances() method that returns both the created instance and its Registration would be very helpful.

Main use case for this that I have in mind is to allow scoped instances to be disposed asynchronously. Simple Injector lacks any features for this, but even if it would, there is no BCL interface (i.e. IAsyncDisposable that allow Simple Injector to detect this.

Since it could take years for this feature is 1. built-in to the framework and developers moved to the latest version of the framework and Simple Injector, developers should be able to have a work around available.

This means that developers should implement their own interface and interact directly with the scope to 'flush' resources to prevent Scope.Dispose from blocking on synchronous I/O.

Example:

using (var scope = AsyncScopedLifestyle.BeginScope(container))
{
    // Resolve (always synchronous)
    var rootType = await container.GetInstance<RootType>();

    // Use (typically async)
    await rootType.Process();

    // Flush (pre-dispose) async (extension method, see below)
    await scope.FlushAsync();
} // Dispose, always synchronous

private static Task FlushAsync(this Scope scope)
{
    // GetCreatedInstances() is added to Scope.
    var items = scope.GetCreatedInstances(); 
    foreach (var scopeItem = items.Reverse()) // always dispose in opposite order
        if (scopeItem.Instance is IAsyncFlushable flushable)
            await flushable.FlushAsync();
}

@dotnetjunkie dotnetjunkie added this to the v4.1 milestone Oct 24, 2017

@dotnetjunkie

This comment has been minimized.

Collaborator

dotnetjunkie commented Mar 1, 2018

I decided to implement a simplified version for now, that just returns all IDisposable instances. This enables the use case described above, while requiring minimal changes to Scope without having to change the performance and memory behavior of Scope:

private static Task FlushAsync(this Scope scope)
{
    // GetDisposables() is added to Scope.
    var disposables = scope.GetDisposables(); 
    foreach (var disposable = disposables.Reverse()) // always dispose in opposite order
        if (disposable is IAsyncFlushable flushable)
            await flushable.FlushAsync();
}

@dotnetjunkie dotnetjunkie changed the title from Allow created scoped instances to be retrieved from their Scope to Allow created disposable instances to be retrieved from their Scope Mar 1, 2018

dotnetjunkie added a commit to simpleinjector/Documentation that referenced this issue Mar 23, 2018

New section "Retrieving list of disposables from the Scope" added to …
…the "Object Lifetime Management" page demonstrating the new Scope.GetDisposables() method of feature simpleinjector/SimpleInjector#478.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment