导读:本期聚焦于小伙伴创作的《C#中的依赖注入是什么?如何实现和使用?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#中的依赖注入是什么?如何实现和使用?》有用,将其分享出去将是对创作者最好的鼓励。

依赖注入是控制反转(IOC)思想的一种具体实现方式,核心是将对象的依赖关系交由外部容器管理,而不是在对象内部自行创建依赖实例,这样可以让代码各部分之间的耦合度更低,后续修改和测试都更方便。

C#中的依赖注入是什么?如何实现和使用?

依赖注入的核心概念

在没有使用依赖注入的场景下,如果一个类需要使用另一个类的功能,通常会在内部直接实例化依赖的对象,比如下面的代码:

// 定义日志接口
public interface ILogService
{
    void WriteLog(string message);
}

// 实现日志接口的具体类
public class FileLogService : ILogService
{
    public void WriteLog(string message)
    {
        Console.WriteLine($"写入文件日志:{message}");
    }
}

// 业务类,内部直接实例化日志服务
public class UserService
{
    private readonly ILogService _logService;
    
    public UserService()
    {
        // 直接在内部创建依赖实例,耦合度高
        _logService = new FileLogService();
    }
    
    public void AddUser(string userName)
    {
        _logService.WriteLog($"添加用户:{userName}");
    }
}

这种写法的问题在于,如果后续要把日志实现换成数据库日志,就需要修改UserService的构造函数,不符合开闭原则。而依赖注入就是把依赖的创建放到外部,由容器来注入到需要的类中。

C#中常见的依赖注入方式

构造函数注入

这是C#中最推荐、最常用的依赖注入方式,通过类的构造函数传入依赖的实例,代码示例如下:

public class UserService
{
    private readonly ILogService _logService;
    
    // 通过构造函数接收依赖,依赖由外部传入
    public UserService(ILogService logService)
    {
        _logService = logService;
    }
    
    public void AddUser(string userName)
    {
        _logService.WriteLog($"添加用户:{userName}");
    }
}

构造函数注入的优势是依赖关系明确,而且可以通过构造函数的参数强制要求依赖必须传入,避免空引用的问题。

属性注入

属性注入是通过公共属性来接收依赖实例,这种方式不是强制要求传入依赖,适合可选的依赖场景,示例如下:

public class UserService
{
    // 定义公共属性接收依赖
    public ILogService LogService { get; set; }
    
    public void AddUser(string userName)
    {
        // 使用时需要判断是否为空
        LogService?.WriteLog($"添加用户:{userName}");
    }
}

ASP.NET Core中的依赖注入使用

ASP.NET Core框架内置了依赖注入容器,不需要额外引入第三方库就可以使用,核心步骤是注册服务和注入使用。

服务注册

Program.cs文件中,通过IServiceCollection来注册服务,需要指定服务的类型和实现类型,以及服务的生命周期:

var builder = WebApplication.CreateBuilder(args);

// 注册服务,指定生命周期为瞬时(每次请求创建新实例)
builder.Services.AddTransient<ILogService, FileLogService>();
// 注册业务服务,依赖ILogService会自动注入
builder.Services.AddTransient<UserService>();

var app = builder.Build();

服务生命周期说明

ASP.NET Core的依赖注入容器支持三种服务生命周期,具体区别如下:

生命周期类型说明
Transient(瞬时)每次请求服务时都会创建一个新的实例,适合轻量级、无状态的服务
Scoped(作用域)在同一个请求作用域内,只会创建一个实例,不同请求之间实例不同,适合和请求相关的服务
Singleton(单例)整个应用程序生命周期内只会创建一个实例,所有请求共享同一个实例,适合全局通用的服务

在控制器中注入使用

注册完成后,就可以在控制器或者其他服务中通过构造函数注入使用注册的服务:

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    private readonly UserService _userService;
    
    // 构造函数注入UserService,UserService依赖的ILogService会自动被容器注入
    public UserController(UserService userService)
    {
        _userService = userService;
    }
    
    [HttpPost("add")]
    public IActionResult AddUser(string userName)
    {
        _userService.AddUser(userName);
        return Ok("用户添加成功");
    }
}

依赖注入的优势总结

  • 降低代码耦合度,依赖的修改不需要改动使用依赖的类
  • 提升代码的可测试性,测试时可以很方便地注入模拟的依赖实例
  • 让代码的依赖关系更清晰,便于后续维护和扩展
  • 框架内置容器减少了额外依赖,使用成本低

Dependency_InjectionIOC构造函数注入服务生命周期修改时间:2026-06-28 17:33:18

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。