【C#】.net core 6.0 依赖注入生命周期

给自己一个目标,然后坚持一段时间,总会有收获和感悟!
对于.net core而言,依赖注入生命周期有三种瞬态(Transient)、作用域(Scoped)和单例(Singleton),无论使用哪种生命周期,都需要确保对象的线程安全性,并正确地处理依赖关系。

在这里插入图片描述

一、程序生命周期

在了解依赖注入的生命周期前,我们先建单了解下应用程序的生命周期,
在 .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 容器、服务注册、服务解析和生命周期管理,帮助开发者更好地组织和管理应用程序中的各种服务对象,提高代码的可扩展性、可测试性和松耦合性。

猜你喜欢

转载自blog.csdn.net/lmy_520/article/details/135191856