- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我想实现 dependency injection ASP.NET Core 中的 (DI)。因此,将此代码添加到 ConfigureServices
方法后,两种方式都有效。
ASP.NET Core 中的services.AddTransient
和service.AddScoped
方法有什么区别?
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddScoped<IEmailSender, AuthMessageSender>();
}
最佳答案
长话短说
Transient objects are always different; a new instance is provided toevery controller and every service.
Scoped objects are the same within a request, but different acrossdifferent requests.
Singleton objects are the same for every object and every request.
为了更清楚,这个例子来自.NET documentation显示差异:
为了演示这些生命周期和注册选项之间的区别,请考虑一个简单的接口(interface),该接口(interface)将一个或多个任务表示为具有唯一标识符 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
实现这些接口(interface),该类在其构造函数中接受 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
服务正在使用一个已知 ID 为 Guid.Empty
的特定实例,因此何时使用此类型将一目了然。我们还注册了一个 OperationService
,它依赖于其他每个 Operation
类型,因此在请求中可以清楚地知道该服务是否正在获取与 Controller 相同的实例,或一个新的,对于每种操作类型。该服务所做的只是将其依赖项作为属性公开,以便它们可以显示在 View 中。
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
类型以及一个 操作服务
。 Index
操作然后显示所有 Controller 和服务的 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();
}
}
}
现在对这个 Controller 操作发出了两个单独的请求:
观察哪些 OperationId
值在请求中和请求之间发生变化。
transient 对象总是不同的;为每个 Controller 和每个服务提供一个新实例。
Scoped objects 在一个请求中是相同的,但在不同的请求中是不同的
单例对象对于每个对象和每个请求都是相同的(不管ConfigureServices
中是否提供实例)
关于c# - AddTransient、AddScoped 和 AddSingleton 服务差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38138100/
我在 asp.net core 中有一个使用内置 DI 框架的应用程序。我想向提供者添加一个按请求(即 transient )服务,但我想在其构造中实际使用该请求。 services.AddTrans
在最新的机器人示例中,我们可以看到机器人正在被添加到服务集合中,如下所示 services.AddTransient(); 但在较旧的样本中,我们看到了以下方法 services.AddBot(opt
我想实现 dependency injection ASP.NET Core 中的 (DI)。因此,将此代码添加到 ConfigureServices 方法后,两种方式都有效。 ASP.NET Cor
根据文档,当我像下面这样配置 DbContext 时,DI 在范围内注册它(每个 http 请求) services.AddEntityFramework() .AddSqlServer()
我有一个用于获取一些信息的服务,该方法在链中有一堆异步调用。 public interface IFooService { Task GetFooAsync(); } 具体类, public
看完this帖子我可以理解 AddTransient、AddScoped 和 AddSingleton 之间的区别,但是,我看不到它们每个的实际用法。 我的理解是 添加 transient 每次客户端
我正在尝试对类 TWService 中的方法进行单元测试,并且需要两个依赖项才能注入(inject),即 IXMLResponseSave 和 IConfiguration。我可以在我的 Fact 中
我是一名优秀的程序员,十分优秀!