TL; DR
Временные объекты всегда разные; новый экземпляр предоставляется каждому контроллеру и каждой службе.
Объекты области видимости одинаковы в запросе, но различны для разных запросов.
Объекты Singleton одинаковы для каждого объекта и каждого запроса.
Для большей ясности этот пример из документации ASP.NET показывает разницу:
Чтобы продемонстрировать разницу между этими параметрами времени жизни и регистрации, рассмотрим простой интерфейс, который представляет одну или несколько задач как операцию с уникальным идентификатором OperationId
. В зависимости от того, как мы настроим время жизни для этой службы, контейнер предоставит запрашивающему классу либо одинаковые, либо разные экземпляры службы. Чтобы было ясно, какое время жизни запрашивается, мы создадим один тип на время жизни:
using System;
namespace DependencyInjectionSample.Interfaces
{
public interface IOperation
{
Guid OperationId { get; }
}
public interface IOperationTransient : IOperation
{
}
public interface IOperationScoped : IOperation
{
}
public interface IOperationSingleton : IOperation
{
}
public interface IOperationSingletonInstance : IOperation
{
}
}
Мы реализуем эти интерфейсы, используя один класс, Operation
который принимает GUID в своем конструкторе, или использует новый GUID, если ни один не указан:
using System;
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Classes
{
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton, IOperationSingletonInstance
{
Guid _guid;
public Operation() : this(Guid.NewGuid())
{
}
public Operation(Guid guid)
{
_guid = guid;
}
public Guid OperationId => _guid;
}
}
Далее, ConfigureServices
каждый тип добавляется в контейнер в соответствии с его именованным временем жизни:
services.AddTransient<IOperationTransient, Operation>();
services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));
services.AddTransient<OperationService, OperationService>();
Обратите внимание, что IOperationSingletonInstance
служба использует конкретный экземпляр с известным идентификатором Guid.Empty
, поэтому будет понятно, когда этот тип используется. Мы также зарегистрировали значение OperationService
, зависящее от каждого из других Operation
типов, чтобы в запросе было ясно, получает ли эта служба тот же экземпляр, что и контроллер, или новый экземпляр для каждого типа операции. Все, что делает этот сервис, представляет его зависимости как свойства, чтобы они могли отображаться в представлении.
using DependencyInjectionSample.Interfaces;
namespace DependencyInjectionSample.Services
{
public class OperationService
{
public IOperationTransient TransientOperation { get; }
public IOperationScoped ScopedOperation { get; }
public IOperationSingleton SingletonOperation { get; }
public IOperationSingletonInstance SingletonInstanceOperation { get; }
public OperationService(IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance instanceOperation)
{
TransientOperation = transientOperation;
ScopedOperation = scopedOperation;
SingletonOperation = singletonOperation;
SingletonInstanceOperation = instanceOperation;
}
}
}
Чтобы продемонстрировать время жизни объекта внутри и между отдельными индивидуальными запросами к приложению, образец включает в себя тип, OperationsController
который запрашивает каждый IOperation
тип, а также тип OperationService
. Затем Index
действие отображает все значения контроллера и службы OperationId
.
using DependencyInjectionSample.Interfaces;
using DependencyInjectionSample.Services;
using Microsoft.AspNetCore.Mvc;
namespace DependencyInjectionSample.Controllers
{
public class OperationsController : Controller
{
private readonly OperationService _operationService;
private readonly IOperationTransient _transientOperation;
private readonly IOperationScoped _scopedOperation;
private readonly IOperationSingleton _singletonOperation;
private readonly IOperationSingletonInstance _singletonInstanceOperation;
public OperationsController(OperationService operationService,
IOperationTransient transientOperation,
IOperationScoped scopedOperation,
IOperationSingleton singletonOperation,
IOperationSingletonInstance singletonInstanceOperation)
{
_operationService = operationService;
_transientOperation = transientOperation;
_scopedOperation = scopedOperation;
_singletonOperation = singletonOperation;
_singletonInstanceOperation = singletonInstanceOperation;
}
public IActionResult Index()
{
// ViewBag contains controller-requested services
ViewBag.Transient = _transientOperation;
ViewBag.Scoped = _scopedOperation;
ViewBag.Singleton = _singletonOperation;
ViewBag.SingletonInstance = _singletonInstanceOperation;
// Operation service has its own requested services
ViewBag.Service = _operationService;
return View();
}
}
}
Теперь к этому действию контроллера подаются два отдельных запроса:
Обратите внимание, какое из OperationId
значений варьируется в запросе и между запросами.
Временные объекты всегда разные; новый экземпляр предоставляется каждому контроллеру и каждой службе.
Объекты области видимости одинаковы в запросе, но различаются в разных запросах
Объекты Singleton одинаковы для каждого объекта и каждого запроса (независимо от того, предоставлен ли экземпляр ConfigureServices
)