Skip to content

[API Proposal]: Add an IServiceLifetimeProvider that takes in a type and returns the lifetime that it was registered with #128251

@bwood4

Description

@bwood4

Background and motivation

Per the discussion in #125609 it seemed like it might be useful to have a service that could retrieve the ServiceLifetime of a given type. There are already similar interfaces that exist, such as IServiceProviderIsService which returns whether or not a type is registered as a service, but none that can retrieve the lifetime.

The driving cause of this proposal is that it makes it easier to deal with the fact that services registered as Transient that implement IDisposable are kept alive until their scope is disposed which commonly leads to memory leaks in long lived scopes, but there may be other benefits.

API Proposal

namespace Microsoft.Extensions.DependencyInjection;

public interface IServiceLifetimeProvider
{
    // Could be this
    ServiceLifetime? GetServiceLifetime(Type serviceType);

    // Or this
    bool TryGetServiceLifetime(Type serviceType, out ServiceLifetime lifetime);
}

API Usage

// Pattern used to create a service and determine if it should be disposed or not by the consumer
public class Consumer()
{
    public Consumer(IServiceProvider serviceProvider, IServiceLifetimeProvider lifetimeProvider)
    {
        IService service;
        bool disposeService;
        // If IService is registered as scoped or singleton, then we just get the service and won't dispose of it when we're done
        if (lifetimeProvider.GetServiceLifetime(typeof(IService)) is ServiceLifetime.Scoped or ServiceLifetime.Singleton)
        {
            service = serviceProvider.GetService<IService>();
            disposeService = false;
        }
        // Otherwise we manually create a new one and know we need to dispose of it. In this case, the IoC container won't track the reference created
       else
       {
            service = ActivatorUtilities.CreateInstance<IService>(serviceProvider);
            disposeService = true;
       }
    }
}

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions