Repository: dotnet/aspnetcore
File: src/Components/Components/src/OwningComponentBase.cs (C#)

Code before:
    protected virtual void Dispose(bool disposing)
    {
        if (!IsDisposed)
        {
            if (disposing)
            {
                if (_scope.HasValue)
                {
                    if (_scope.Value is IDisposable disposable)
                    {
                        disposable.Dispose();
                    }
                    _scope = null;
                }
            }
            IsDisposed = true;
        }
    }

    /// <summary>
    /// Asynchronously releases the service scope used by the component.
    /// </summary>
    /// <returns>A task that represents the asynchronous dispose operation.</returns>
    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        await DisposeAsyncCore().ConfigureAwait(false);

        Dispose(disposing: false);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Asynchronously releases the service scope used by the component.
    /// </summary>
    /// <returns>A task that represents the asynchronous dispose operation.</returns>
    protected virtual async ValueTask DisposeAsyncCore()
    {
        if (!IsDisposed && _scope.HasValue)
        {
            await _scope.Value.DisposeAsync().ConfigureAwait(false);
            _scope = null;
        }

        IsDisposed = true;
    }
}

/// <summary>
/// A base class that creates a service provider scope, and resolves a service of type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The service type.</typeparam>

Review comment (suggestion):
Note for API review. Since this is a "standard" implementation pattern that people might have followed within their own classes, it might be problematic if we use the same name (as the name will start conflicting) so we should consider "breaking away" from this and using a different name to "avoid the breackage".

Overall, I think this is potentially uncommon since OwningComponentBase is not common in the first place.

Code after:
        if (!IsDisposed)
        {
            if (disposing && _scope.HasValue && _scope.Value is IDisposable disposable)
            {
                disposable.Dispose();
                _scope = null;
            }

            IsDisposed = true;
        }
    }

    /// <inhertidoc />
    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        await DisposeAsyncCore().ConfigureAwait(false);

        Dispose(disposing: false);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Asynchronously releases the service scope used by the component.
    /// </summary>
    /// <returns>A task that represents the asynchronous dispose operation.</returns>
    protected virtual async ValueTask DisposeAsyncCore()
    {
        if (!IsDisposed && _scope.HasValue)
        {
            await _scope.Value.DisposeAsync().ConfigureAwait(false);
            _scope = null;
        }

        IsDisposed = true;
    }
}

/// <summary>
/// A base class that creates a service provider scope, and resolves a service of type <typeparamref name="TService"/>.
/// </summary>
/// <typeparam name="TService">The service type.</typeparam>
/// <remarks>
/// Use the <see cref="OwningComponentBase{TService}"/> class as a base class to author components that control
/// the lifetime of a service or multiple services. This is useful when using a transient or scoped service that
/// requires disposal such as a repository or database abstraction. Using <see cref="OwningComponentBase{TService}"/>
/// as a base class ensures that the service and relates services that share its scope are disposed with the component.
/// </remarks>
public abstract class OwningComponentBase<TService> : OwningComponentBase, IDisposable where TService : notnull
{
    private TService _item = default!;