在 .NET Core 中,依赖注入(Dependency Injection,DI)是一种实现控制反转(Inversion of Control,IoC)的技术,它通过将依赖对象注入到需要它们的对象中,来实现对象之间的解耦。依赖注入的生命周期决定了对象在应用程序中的创建和管理方式。常见的生命周期有三种:Transient(瞬态)Scoped(作用域)Singleton(单例)


1. Transient(瞬态)

定义:

每次请求时都会创建一个新的实例。

特点:

  • 每次注入时都会创建一个新的对象。
  • 对象的生命周期仅限于当前请求。
  • 适用于轻量级、无状态的服务。

使用场景:

  • 适用于每次请求都需要独立实例的场景,例如工具类、无状态服务等。

示例:

public interface ITransientService
{
    Guid GetOperationId();
} public class TransientService : ITransientService
{
    private readonly Guid _operationId;     public TransientService()
    {
        _operationId = Guid.NewGuid();
    }     public Guid GetOperationId() => _operationId;
}

Startup.cs 中注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ITransientService, TransientService>();
}

在控制器中使用:

public class HomeController : Controller
{
    private readonly ITransientService _transientService1;
    private readonly ITransientService _transientService2;     public HomeController(ITransientService transientService1, ITransientService transientService2)
    {
        _transientService1 = transientService1;
        _transientService2 = transientService2;
    }     public IActionResult Index()
    {
        _transientService1.DoWork();
        _transientService2.DoWork();         // 验证是否为不同实例
        Console.WriteLine(_transientService1 == _transientService2);  // 输出:False         return Ok();
    }
}

输出:

Transient Service: Doing work...
    Transient Service: Doing work...
        False

2. Scoped(作用域)

定义:

在同一个作用域内,对象是单例的;但在不同的作用域中,会创建新的实例。

特点:

  • 对象的生命周期与请求的作用域一致。
  • 适用于需要在请求范围内共享状态的服务。

使用场景:

  • 适用于需要在请求范围内共享状态的场景,例如数据库上下文、工作单元模式等。

示例:

public interface IScopedService
{
    void DoWork();
} public class ScopedService : IScopedService
{
    public void DoWork()
    {
        Console.WriteLine("Scoped Service: Doing work...");
    }
}

Startup.cs 中注册

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IScopedService, ScopedService>();
}

在控制器中使用:

public class HomeController : Controller
{
    private readonly IScopedService _scopedService1;
    private readonly IScopedService _scopedService2;     public HomeController(IScopedService scopedService1, IScopedService scopedService2)
    {
        _scopedService1 = scopedService1;
        _scopedService2 = scopedService2;
    }     public IActionResult Index()
    {
        _scopedService1.DoWork();
        _scopedService2.DoWork();         // 验证是否为相同实例
        Console.WriteLine(_scopedService1 == _scopedService2);  // 输出:True         return Ok();
    }
}

输出:

Scoped Service: Doing work...
    Scoped Service: Doing work...
        True

3. Singleton(单例)

定义:

在整个应用程序生命周期中,只创建一个实例。

特点:

  • 对象的生命周期与应用程序的生命周期一致。
  • 适用于全局共享的服务,如配置管理、日志记录等。

使用场景:

  • 适用于需要全局共享的场景,例如配置管理、缓存、日志记录等。

示例:

public interface ISingletonService
{
    void DoWork();
} public class SingletonService : ISingletonService
{
    public void DoWork()
    {
        Console.WriteLine("Singleton Service: Doing work...");
    }
}

Startup.cs 中注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ISingletonService, SingletonService>();
}

在控制器中使用:

public class HomeController : Controller
{
    private readonly ISingletonService _singletonService1;
    private readonly ISingletonService _singletonService2;     public HomeController(ISingletonService singletonService1, ISingletonService singletonService2)
    {
        _singletonService1 = singletonService1;
        _singletonService2 = singletonService2;
    }     public IActionResult Index()
    {
        _singletonService1.DoWork();
        _singletonService2.DoWork();         // 验证是否为相同实例
        Console.WriteLine(_singletonService1 == _singletonService2);  // 输出:True         return Ok();
    }
}

输出:

Singleton Service: Doing work...
Singleton Service: Doing work...
True

总结

生命周期 定义 特点 使用场景
Transient 每次请求时创建新的实例 每次注入时都会创建一个新的对象 轻量级、无状态的服务,如工具类、无状态服务
Scoped 在同一个作用域内,对象是单例的 对象的生命周期与请求的作用域一致 需要在请求范围内共享状态的服务,如数据库上下文
Singleton 在整个应用程序生命周期中,只创建一个实例 对象的生命周期与应用程序的生命周期一致 全局共享的服务,如配置管理、日志记录

通过合理选择依赖注入的生命周期,我们可以实现对象的灵活管理和高效使用,从而提高应用程序的性能和可维护性。

.NetCore依赖注入(DI)之生命周期的更多相关文章

  1. Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

    1.前言 面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI).控制反转(IOC)及其容器等概念.在学习Core依赖注入.服务生命周期之前,下面让我们先 ...

  2. 018-019 NET5_内置容器支持依赖注入+IServiceCollection的生命周期

    概念: DI依赖注入: IServiceCollection仅支持构造函数注入 什么是依赖注入? 如果对象A依赖对象B,对象B依赖对象C,就可以先构造对象C,然后传递给对象B,再把对象B传递给A.得到 ...

  3. Console app 里的依赖注入及其实例生命周期

    依赖注入是 ASP.NET Core 里的核心概念之一,我们平常总是愉快地在Startup类的ConfigureServices方法里往IServiceCollection里注册各种类型,以致有一些同 ...

  4. 从EFCore上下文的使用到深入剖析DI的生命周期最后实现自动属性注入

    故事背景 最近在把自己的一个老项目从Framework迁移到.Net Core 3.0,数据访问这块选择的是EFCore+Mysql.使用EF的话不可避免要和DbContext打交道,在Core中的常 ...

  5. spring-framework-中文文档三:依赖注入DI

    5.4依赖性 典型的企业应用程序不包含单个对象(或Spring的说法中的bean).即使最简单的应用程序也有几个对象一起工作来展示最终用户将其视为一个连贯的应用程序.下一节将介绍如何从定义许多独立的b ...

  6. 20181123_控制反转(IOC)和依赖注入(DI)

    一.   控制反转和依赖注入: 控制反转的前提, 是依赖倒置原则, 系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖 (依赖抽象,而不是细节) 如果要想做到控制反转(IOC), 就必须要使 ...

  7. 轻松学,浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI) 依赖注入和控制反转的理解,写的太好了。

    轻松学,浅析依赖倒置(DIP).控制反转(IOC)和依赖注入(DI) 2017年07月13日 22:04:39 frank909 阅读数:14269更多 所属专栏: Java 反射基础知识与实战   ...

  8. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  9. .NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)

    依赖倒置原则(DIP) 依赖倒置(Dependency Inversion Principle,缩写DIP)是面向对象六大基本原则之一.他是指一种特定的的解耦形式,使得高层次的模块不依赖低层次的模块的 ...

  10. ASP.NET Core依赖注入(DI)

    ASP.NET Core允许我们指定注册服务的生存期.服务实例将根据指定的生存时间自动处理.因此,我们无需担心清理此依赖关系,他将由ASP.NET Core框架处理.有如下三种类型的生命周期. 关于依 ...

随机推荐

  1. git知识点,常用命令

    git理论知识 git的服务器端(remote)端包含多个repository,每个repository可以理解为一个项目. 而每个repository下有多个branch."origin& ...

  2. linu管理文本文件

    vi\vim编辑器的三种工作模式 命令模式(Command mode):按键编辑器都理解为命令,以命令驱动执行不同的功能.此模型下,不能自由进行文本编辑. 输入模式(Insert mode):也就是所 ...

  3. php在大并发下redis锁实现

    在现如今电商盛行的时期,会出现很多促销活动,最为常见的就是秒杀.在秒杀系统中最为常见的问题就是会出现超卖的情况,那么如何来杜绝超卖的情形了,在业务逻辑层面可以使用缓存以及加锁的手法来避免超卖的情形. ...

  4. games101_Homework6

    实现 Ray-Bounding Volume 求交与 BVH 查找 在本次编程练习中,你需要实现以下函数: • IntersectP(const Ray& ray, const Vector3 ...

  5. Mysql数据类型面试题15连问

    整数类型的 UNSIGNED 属性有什么用? MySQL 中的整数类型可以使用可选的 UNSIGNED 属性来表示不允许负值的无符号整数.使用 UNSIGNED 属性可以将正整数的上限提高一倍,因为它 ...

  6. .NET 9使用Scalar替代Swagger

    背景 .NET 9刚刚正式发布了,如果你创建一个空的Asp.Net Core 9.0的Web API项目,启动之后,你会惊讶地发现陪伴你多年的Swagger没有了!--这是因为ASP.NET Core ...

  7. 4G模组软件指南 | 必读篇之模块信息(hmeta)

    今天我讲解的这篇关于4G模组软件的模块信息属于必读篇,望珍惜! 1.模块信息概述 模块信息是每一个模块携带的信息,就像人的身份证一样,这些信息确定了模块的唯一性; 包含设备唯一id,硬件型号,模组的硬 ...

  8. json-lib(ezmorph)、gson、flexJson、fastjson、jackson对比,实现java转json,json转java

    json-lib(ezmorph).gson.flexJson.fastjson.jackson对比,实现java转json,json转java 本文中所讲的所有代码都在此:json-test 目前关 ...

  9. 设计模式【3.3】-- CGLIB动态代理源码解读

    cglib 动态代理 cglib介绍 CGLIB 是一个开源项目,一个强大高性能高质量的代码生成库,可以在运行期拓展 Java 类,实现 Java 接口等等.底层是使用一个小而快的字节码处理框架 AS ...

  10. 李世铭SFE|销售的四种境界-与之匹配的CRM功能

    销售有四种境界,与之匹配的也应有四种不同的CRM系统的功能. 1.服务型销售 这类销售代表人数最为众多,超过半数的销售代表皆属于服务型.他们主要基于客户的需求,来提供相应的解决方案,或者公司所规定的某 ...