Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用IServiceCollection.AddTransient、IServiceCollection.AddSingleton和IServiceCollectionAddScope方法的实际场景是什么?_C#_Asp.net Core - Fatal编程技术网

C# 使用IServiceCollection.AddTransient、IServiceCollection.AddSingleton和IServiceCollectionAddScope方法的实际场景是什么?

C# 使用IServiceCollection.AddTransient、IServiceCollection.AddSingleton和IServiceCollectionAddScope方法的实际场景是什么?,c#,asp.net-core,C#,Asp.net Core,阅读本文后,我可以理解AddTransient、AddScoped和AddSingleton之间的区别,但是,我看不到它们的实际用法 我的理解是 AddTransient 每次客户端请求时都创建一个新实例 services.AddTransient<IDataAccess, DataAccess>(); 这意味着每个web请求将有自己的购物车实例,intern意味着每个用户/客户机将有自己的http web请求购物车实例 AddSingleton 为所有http web请求创建单个

阅读本文后,我可以理解
AddTransient
AddScoped
AddSingleton
之间的区别,但是,我看不到它们的实际用法

我的理解是

AddTransient

每次客户端请求时都创建一个新实例

services.AddTransient<IDataAccess, DataAccess>();
这意味着每个web请求将有自己的购物车实例,intern意味着每个用户/客户机将有自己的http web请求购物车实例

AddSingleton

为所有http web请求创建单个实例

使用AddSingleton

在一个示例应用程序中找到了这段代码,但我不明白它是如何有用的

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
services.AddSingleton();

是否有人能给出一个恰当的实际例子,说明何时使用AddSingleton,并检查我对AddTransient和AddScoped的理解是否正确?

您对所有3个作用域的理解都是正确的

当组件无法共享时,将使用瞬态。一个非线程安全的数据库访问对象就是一个例子

作用域可用于实体框架数据库上下文。主要原因是,从数据库中获取的实体将附加到请求中所有组件所看到的相同上下文。当然,如果您计划并行使用它进行查询,那么就不能使用Scoped

作用域对象的另一个示例是某种
RequestContext
类,它包含调用方的用户名等。中间件/MVC过滤器可以请求它并填写信息,其他组件也可以请求它,它肯定会包含当前请求的信息

单例组件总是共享的,因此它们最适合于不需要绑定到请求的线程安全组件。例如,
IOptions
,它允许访问配置设置。在单个静态
HttpClient
实例上使用
SendAsync
HttpClient
包装类也将是完全线程安全的,并且很适合作为单例

请注意,如果您有一个依赖于作用域组件的单例组件,那么它的依赖关系将在它之前得到处理。因此,一个组件不能依赖于另一个范围比它小的组件。

我已经看到了“just use
AddTransient()
”视图,但我不同意

考虑一下内存分配 我讨厌在我不需要的时候分配东西,所以如果我知道我正在创建线程安全的东西,或者我有明确的文档说明拥有一个单例实例是预期用途,那么我就创建一个单例

AddSingleton() 下面是ApplicationInsights TelemetryClient实例作为一个单例。他们的文件说这是可行的

telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);
services.AddSingleton<TelemetryClient>(telemetryClient);
。。。整个应用程序中只有一个实例,但是通过使用
services.AddSingleton()
我们可以使用依赖项注入直接访问它

AddScoped() 对我来说,
addScope()
的一个例子是,我想将获取应用程序洞察所需的JavaScript嵌入到网页中,但我使用,因此我需要在任何页面JavaScript上放置一个nonce。我有一些代码可以帮助我做到这一点

services.AddScoped<ApplicationInsightsJsHelper>();
services.addScope();
AddTransient()
我还没有发现需要对任何东西使用
AddTransient()
。这可能是因为我不认为每次我需要创造的东西都是“服务”。。。它们只是我新发现的变量。在某种意义上,
AddTransient()
是工厂模式的一种隐藏用法。。。你不用调用静态的
MyServiceFactory.Create()
函数,而是让依赖项注入(有效地)为你做同样的事情。

谢谢yo Juunas,这是一个很好的解释,但是,我希望有一些具体的例子来回答这个问题-可能现在问这个问题还为时过早。如果我读对了这篇文章,然后,Singleton更倾向于使用作用域和瞬态(因为不必要地重新创建对象通常看起来是不必要的),但是对于我们不能使用它的情况(例如,由于非线程安全代码),我们必须使用另外两种情况中的一种(取决于我们的需要)。我至少是这样想的:)@PeppeL-G如果DbContext对象设置为Transient,是否正确?DbConext类来自实体框架,用于访问数据库对象,如表、视图等。@YawarMurtaza我会说是的,假设使用它的服务也被标记为瞬态。EF上下文可以是暂时的或限定范围的,而不是真正的单例。经常使用作用域的原因是,请求中的多个服务可以对同一个上下文实例进行修改和查询,最后SaveChanges()一次保存所有服务。瞬态意味着您不能这样做,但提供了更高的隔离度(当然:)
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Configuration.GetValue<string>("storageAccountConnectionString"));
CloudTableClient someTableClient = storageAccount.CreateCloudTableClient();
services.AddSingleton<CloudTableClient>(someTableClient);
public static readonly CloudTableClient cloudTableClient = new CloudTableClient(...);
services.AddScoped<ApplicationInsightsJsHelper>();