.NET 中的依赖注入(四):生命周期
2022/1/17 6:06:21
本文主要是介绍.NET 中的依赖注入(四):生命周期,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文示例代码,均采用 .NET 6,具体的代码可以在这个仓库 Articles.DI 中获取。
前面的文章中,在注册服务时,统一使用了 services.AddSingleton<TService, TImplementation>()
的形式来注册服务,这个方法的具体含义是什么?有没有其他类似的方法?而且我们还有一个疑问,容器在构造服务时,服务的生命周期是怎么样的?服务被申请一次,就构造一次吗?还是整个程序周期,只构造一次?如果我们要自定义每个服务有不同的生命周期时,又该怎么做?下面,我们将一起探寻服务的生命周期。
生命周期
注册到容器时,服务的生命周期分为三种
生命周期 | 何时创建 | 调用方法 |
---|---|---|
瞬时 / Transient | 每次请求,都会创建一个新的实例 | AddTransient() |
范围 / Scoped | 在指定的范围内,第一次请求时会创建一个实例 重复请求时,会返回同一个实例 |
AddScoped() |
单例 / Singleton | 在整个程序生命周期,只会创建一次 后续所有请求,都会返回同一个实例 |
AddSingleton() |
参考实际代码,我们可以更直观的理解依赖注入中的三种生命周期,下面的代码可以在微软的 .NET 文档中找到对应的文章——教程:在 .NET 中使用依赖注入。或者可以在这个仓库中直接查看获取源码
// https://github.com/alva-lin/Articles.DI/tree/master/ConsoleApp1 // 01. 声明接口以及实现类 public interface IOperation { string OperationId { get; } } public interface ITransientOperation : IOperation {} public interface IScopedOperation : IOperation {} public interface ISingletonOperation : IOperation {} public class DefaultOperation : ITransientOperation, IScopedOperation, ISingletonOperation { // 创建一个 Guid,取最后 4 个字符 public string OperationId { get; } = Guid.NewGuid().ToString()[^4..]; }
// 02. 创建一个服务,它依赖上面几个 Operation public class OperationLogger { private readonly ITransientOperation _transientOperation; private readonly IScopedOperation _scopedOperation; private readonly ISingletonOperation _singletonOperation; public OperationLogger(ITransientOperation transientOperation, IScopedOperation scopedOperation, ISingletonOperation singletonOperation) { _transientOperation = transientOperation; _scopedOperation = scopedOperation; _singletonOperation = singletonOperation; } public void LogOperations(string scope) { LogOperation(_transientOperation, scope, "Always different"); LogOperation(_scopedOperation, scope, "Changes only with scope"); LogOperation(_singletonOperation, scope, "Always the same"); } private static void LogOperation<T>(T operation, string scope, string message) where T : IOperation { Console.WriteLine($"{scope}: {typeof(T).Name,-19} [{operation.OperationId} {message,-23}]"); } }
// 03. 注册服务并启动程序 using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices(services => { // 将三种 Operation 分别注册为三种声明周期 services.AddTransient<OperationLogger>() .AddTransient<ITransientOperation, DefaultOperation>() .AddScoped<IScopedOperation, DefaultOperation>() .AddSingleton<ISingletonOperation, DefaultOperation>(); }) .Build(); ExemplifyScoping(host.Services, "Scope 1"); ExemplifyScoping(host.Services, "Scope 2"); await host.RunAsync(); static void ExemplifyScoping(IServiceProvider services, string scope) { using IServiceScope serviceScope = services.CreateScope(); IServiceProvider provider = serviceScope.ServiceProvider; var logger = provider.GetRequiredService<OperationLogger>(); logger.LogOperations($"{scope}: Call 1 ..."); Console.WriteLine(); logger = provider.GetRequiredService<OperationLogger>(); logger.LogOperations($"{scope}: Call 2 ..."); Console.WriteLine(); }
运行上述代码,可以获得下面的结果
Scope 1: Call 1 ...: ITransientOperation [b672 Always different ] Scope 1: Call 1 ...: IScopedOperation [afd8 Changes only with scope] Scope 1: Call 1 ...: ISingletonOperation [21b3 Always the same ] Scope 1: Call 2 ...: ITransientOperation [b6fc Always different ] Scope 1: Call 2 ...: IScopedOperation [afd8 Changes only with scope] Scope 1: Call 2 ...: ISingletonOperation [21b3 Always the same ] Scope 2: Call 1 ...: ITransientOperation [ef31 Always different ] Scope 2: Call 1 ...: IScopedOperation [46d1 Changes only with scope] Scope 2: Call 1 ...: ISingletonOperation [21b3 Always the same ] Scope 2: Call 2 ...: ITransientOperation [9864 Always different ] Scope 2: Call 2 ...: IScopedOperation [46d1 Changes only with scope] Scope 2: Call 2 ...: ISingletonOperation [21b3 Always the same ]
比对程序输出的日志,可以看出,每个 ITransientOperation
的输出都会不一样;而 IScopedOperation
在相同的范围内输出内容一样,在不同的范围间输出内容不同;最后一个 ISingletonOperation
,每次的输出都是相同的。这样的输出结果,也符合我们前面的表格展示内容。
参考链接
.NET 中的依赖关系注入
教程:在 .NET 中使用依赖注入
这篇关于.NET 中的依赖注入(四):生命周期的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-12-06使用Microsoft.Extensions.AI在.NET中生成嵌入向量
- 2024-11-18微软研究:RAG系统的四个层次提升理解与回答能力
- 2024-11-15C#中怎么从PEM格式的证书中提取公钥?-icode9专业技术文章分享
- 2024-11-14云架构设计——如何用diagrams.net绘制专业的AWS架构图?
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#