给自己一个目标,然后坚持一段时间,总会有收获和感悟!
对于.net core而言,依赖注入生命周期有三种瞬态(Transient)、作用域(Scoped)和单例(Singleton),无论使用哪种生命周期,都需要确保对象的线程安全性,并正确地处理依赖关系。
目录
- 一、程序生命周期
- 2.1、构造函数
- 2.2、配置
- 2.3、启动
- 2.4、运行
- 2.5、停止
- 2.6、释放资源
- 二、依赖注入生命周期
- 2.1、瞬态生命周期
- 2.2、作用域生命周期
- 2.3、单例生命周期
- 三、代码举例
- 3.1、瞬态生命周期
- 3.2、作用域生命周期
- 3.3、单例生命周期
- 四、自定义管理
- 五、依赖注入原理
一、程序生命周期
在了解依赖注入的生命周期前,我们先建单了解下应用程序的生命周期,
在 .NET Core 6.0 中,应用程序的生命周期包括以下阶段:
2.1、构造函数
在应用程序启动时,会调用构造函数来创建主机(Host)对象。
2.2、配置
在构造函数之后,会调用配置方法来设置应用程序的配置,例如添加服务、配置中间件等。
2.3、启动
配置完成后,会调用启动方法来启动应用程序,包括启动 HTTP 服务器、启动后台服务等。
2.4、运行
应用程序开始监听请求并进行处理,这是应用程序的主要运行阶段。
2.5、停止
当应用程序接收到停止信号时(如收到终止命令或服务器关闭),会触发停止方法来执行一些清理操作。
2.6、释放资源
在停止之后,应用程序释放资源并进行善后工作,如关闭数据库连接、释放资源等。
除了上述阶段外,还可以通过使用生命周期中的事件钩子来添加自定义逻辑,以便在特定时刻执行某些代码。
需要注意的是,不同类型的应用程序(如控制台应用程序、Web 应用程序等)的生命周期可以有所不同,但上述阶段是通用的核心生命周期。
二、依赖注入生命周期
在 .NET Core 6.0 中,依赖注入服务的生命周期有三种:瞬态(Transient)、作用域(Scoped)和单例(Singleton)。
2.1、瞬态生命周期
在每次请求时都会创建一个新的实例,并在请求结束时立即销毁该实例,适用于轻量级的对象。这种生命周期可以通过
services.AddTransient 方法进行注册。
2.2、作用域生命周期
在每个 HTTP 请求处理期间,会使用同一个实例,请求结束时实例也会被销毁,适用于线程安全的对象,如 EF 上下文。这种生命周期可以通过
services.AddScoped 方法进行注册。
2.3、单例生命周期
在整个应用程序生命周期中只会创建一个实例,适用于被多处使用的对象,如配置信息、单例服务等。这种生命周期可以通过
services.AddSingleton 方法进行注册。
除了上述生命周期外,还可以通过 services.AddSingleton 方法传递一个工厂方法,以实现自定义的生命周期管理。
无论使用哪种生命周期,都需要确保对象的线程安全性,并正确地处理依赖关系。正确使用依赖注入可以提高代码的可测试性和可维护性,将对象的创建和销毁等生命周期管理交由 DI 容器负责,从而简化代码的编写。
三、代码举例
当使用 .NET Core 6.0 进行依赖注入时,可以使用以下代码示例来演示瞬态、作用域和单例生命周期
3.1、瞬态生命周期
public interface ITransientService
{
void DoSomething();
}
public class TransientService : ITransientService
{
private readonly Guid _id;
public TransientService()
{
_id = Guid.NewGuid();
}
public void DoSomething()
{
Console.WriteLine($"TransientService ID: {_id}");
}
}
// 在 Startup.cs 的 ConfigureServices 方法中添加以下代码:
services.AddTransient<ITransientService, TransientService>();
// 在需要使用服务的地方,使用构造函数注入:
public class MyController
{
private readonly ITransientService _transientService;
public MyController(ITransientService transientService)
{
_transientService = transientService;
}
// 使用服务
public void MyAction()
{
_transientService.DoSomething();
}
}
3.2、作用域生命周期
public interface IScopeService
{
void DoSomething();
}
public class ScopeService : IScopeService
{
private readonly Guid _id;
public ScopeService()
{
_id = Guid.NewGuid();
}
public void DoSomething()
{
Console.WriteLine($"ScopeService ID: {_id}");
}
}
// 在 Startup.cs 的 ConfigureServices 方法中添加以下代码:
services.AddScoped<IScopeService, ScopeService>();
// 在需要使用服务的地方,使用构造函数注入:
public class MyController
{
private readonly IScopeService _scopeService;
public MyController(IScopeService scopeService)
{
_scopeService = scopeService;
}
// 使用服务
public void MyAction()
{
_scopeService.DoSomething();
}
}
3.3、单例生命周期
public interface ISingletonService
{
void DoSomething();
}
public class SingletonService : ISingletonService
{
private readonly Guid _id;
public SingletonService()
{
_id = Guid.NewGuid();
}
public void DoSomething()
{
Console.WriteLine($"SingletonService ID: {_id}");
}
}
// 在 Startup.cs 的 ConfigureServices 方法中添加以下代码:
services.AddSingleton<ISingletonService, SingletonService>();
// 在需要使用服务的地方,使用构造函数注入:
public class MyController
{
private readonly ISingletonService _singletonService;
public MyController(ISingletonService singletonService)
{
_singletonService = singletonService;
}
// 使用服务
public void MyAction()
{
_singletonService.DoSomething();
}
}
以上示例展示了如何在 .NET Core 6.0 中注册和使用瞬态、作用域和单例生命周期的依赖注入服务。
根据实际需求,选择适合的生命周期以确保正确的对象创建和销毁,并维护正确的对象状态。
四、自定义管理
当通过 services.AddSingleton 方法传递一个工厂方法时,可以使用委托来创建自定义的生命周期管理。
-
下面是一个示例代码:
首先,定义一个自定义的服务类 CustomService:
public class CustomService
{
public DateTime CreatedAt { get; }public CustomService()
{
CreatedAt = DateTime.Now;
}
}
然后,在应用程序启动时,注册该服务并传递一个工厂方法来实现自定义的生命周期管理:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(serviceProvider =>
{
// 创建 CustomService 对象,并进行自定义的处理
var customService = new CustomService();
// 在此可以添加自定义的生命周期管理逻辑
return customService;
});
// 其他服务的注册
// ...
}
}
在上述示例中,通过 services.AddSingleton(serviceProvider => { … }) 方法向 DI 容器注册了一个 CustomService 类型的单例服务,传递了一个工厂方法作为参数。
在这个工厂方法中,我们可以自定义创建 CustomService 对象的方式,并进行额外的处理。
这样,当通过 DI 容器解析 CustomService 时,每次获取到的都是通过工厂方法创建的同一个实例,而且可以根据需要在工厂方法中进行自定义的生命周期管理操作。
需要注意的是,工厂方法可以接收一个 IServiceProvider 参数,以便在创建服务实例时获取其他已注册的服务。这在某些场景下可能会很有用。
五、依赖注入原理
在 .NET Core 6.0 中,依赖注入(DI)是一个重要的功能,它通过提供、解析和跟踪应用程序中的各种服务对象来帮助解耦和组织代码。
依赖注入的原理主要包括以下几个方面:
1.服务注册:在应用程序启动时,通过使用
IServiceCollection 接口的 AddTransient、AddScoped、AddSingleton 等方法将服务类型和其生命周期添加到 DI 容器中。
2.服务解析:当需要使用某个服务的实例时,可以通过 DI 容器提供的
IServiceProvider 接口的 GetRequiredService、GetService 等方法来获取该服务的实例,其中 T 是服务类型。
3.生命周期管理:DI 容器会根据服务的生命周期设置来控制服务对象的创建和销毁。根据服务的生命周期,可以使用
AddTransient、AddScoped、AddSingleton 方法注册瞬态、作用域和单例服务。
- 瞬态(Transient)生命周期表示每次通过 DI 容器获取服务时都会创建一个新的实例。
- 作用域(Scoped)生命周期表示在同一个作用域内(例如,相同的 HTTP 请求)获取服务时将使用同一个实例。
- 单例(Singleton)生命周期表示整个应用程序中只创建一个实例,并且所有的请求都会使用同一个实例。
1.依赖关系解析:DI 容器能够自动解析服务对象之间的依赖关系,即当需要解析某个服务时,DI 容器会自动创建该服务所依赖的其他服务实例,并将其注入到需要的位置上。
2.服务扩展:通过扩展
IServiceCollection 接口,可以自定义添加和配置服务,使得 DI 容器能够支持更多的功能和扩展。
总体而言,.NET Core 6.0 的依赖注入原理基于 DI 容器、服务注册、服务解析和生命周期管理,帮助开发者更好地组织和管理应用程序中的各种服务对象,提高代码的可扩展性、可测试性和松耦合性。