当前位置: 首页 > ops >正文

ASP.Net依赖注入!使用Microsoft.Extensions.DependencyInjection配置依赖注入

文章目录

  • 前言
  • 一、依赖注入是什么?
  • 二、使用步骤
  • 三、示例
  • 四、依赖注入服务生命周期
  • 五、依赖注入的方式


前言

ASP.Net依赖注入!使用Microsoft.Extensions.DependencyInjection配置依赖注入

一、依赖注入是什么?

百度百科:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
(简单解释)
依赖注入就是IOC容器会自动给你创建和维护对象,你只需要直接使用这个对象即可。

二、使用步骤

第一、导入Microsoft.Extensions.DependencyInjection库和Microsoft.Extensions.Hosting库

Host.CreateDefaultBuilder(args).ConfigureServices((hostContext, services) =>{// 注册服务services.AddSingleton<LoginForm>();services.AddSingleton<UserService>();// 其他服务注册...});

1、调用 Host.CreateDefaultBuilder 方法创建一个默认的主机构建器。
CreateDefaultBuilder 方法会配置一些默认的服务和设置,包括:
加载配置文件(如 appsettings.json)。
配置日志记录。
设置内容根目录。
args 参数通常是从 Main 方法传递的命令行参数
2、ConfigureServices((hostContext, services) => { … }):
使用 ConfigureServices 方法配置依赖注入容器。
hostContext 参数提供了主机的配置和环境信息。
services 参数是一个 IServiceCollection,用于注册服务。
3、服务注册:
services.AddSingleton():将 LoginForm 类注册为单例服务。这意味着在应用程序的整个生命周期内只会创建一个 LoginForm 的实例。
services.AddSingleton():将 UserService 类注册为单例服务。同样,这个服务在应用程序的整个生命周期内只会创建一个实例。
这些服务注册确保了 LoginForm 和 UserService 可以通过依赖注入的方式在应用程序中使用。

三、示例

主程序入口

class Program
{static void Main(string[] args){using var host = CreateHostBuilder(args).Build();var loginForm = host.Services.GetRequiredService<LoginForm>();Application.Run(loginForm);}public static IHost CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureServices((hostContext, services) =>{services.AddSingleton<LoginForm>();services.AddSingleton<UserService>();});
}

窗体类

public partial class LoginForm : Form
{private readonly UserService _userService;public LoginForm(UserService userService){InitializeComponent();_userService = userService;}private void LoginButton_Click(object sender, EventArgs e){var username = UsernameTextBox.Text;var password = PasswordTextBox.Text;if (_userService.ValidateUser(username, password)){MessageBox.Show("Login successful!");}else{MessageBox.Show("Invalid username or password.");}}
}

用户服务类

public class UserService
{public bool ValidateUser(string username, string password){// 实现用户验证逻辑return username == "admin" && password == "password";}
}

使用流程解释

  1. 服务注册
    在 CreateHostBuilder 方法中,使用 services.AddSingleton() 将 UserService 类注册到依赖注入容器中。这告诉容器 UserService 是一个单例服务,即在整个应用程序生命周期内只会创建一个实例。
public static IHost CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureServices((hostContext, services) =>{services.AddSingleton<LoginForm>();services.AddSingleton<UserService>();});
  1. 构造函数注入
    在 LoginForm 类中,构造函数定义了一个参数 UserService userService。这表示 LoginForm 依赖于 UserService,并且这个依赖项需要在创建 LoginForm 实例时提供。
public partial class LoginForm : Form
{private readonly UserService _userService;public LoginForm(UserService userService){InitializeComponent();_userService = userService;}
}
  1. 依赖注入容器的作用
    当使用 host.Services.GetRequiredService() 从依赖注入容器中获取 LoginForm 实例时,容器会自动解析 LoginForm 的构造函数所需的参数。
    容器检查 LoginForm 的构造函数,发现它需要一个 UserService 类型的参数。
    容器已经在前面注册了 UserService 为单例服务,因此它会使用之前创建的 UserService 实例来满足这个依赖。
    容器将这个 UserService 实例传递给 LoginForm 的构造函数,从而完成依赖注入。
  2. 获取服务实例
    最终,host.Services.GetRequiredService() 返回一个完全初始化的 LoginForm 实例,其中 _userService 字段已经被注入了 UserService 的实例。
var loginForm = host.Services.GetRequiredService<LoginForm>();

四、依赖注入服务生命周期

我得解释 AddScoped,它用于注册作用域服务。这类服务在同一个作用域内共享一个实例,通常用于处理单个请求或操作。我得给用户一个具体的例子,比如数据访问层的 EF Core DbContext,来说明它的实际应用。
接着,我得解释 AddSingleton,它用于注册单例服务。这个很好理解,就是整个应用程序生命周期内只创建一个实例,适合无状态的工具类或跨请求共享数据的服务。我得强调单例服务的使用注意事项,避免因状态共享导致的线程安全问题。
最后,我得解释 AddTransient,它用于注册瞬态服务。这种服务每次请求都会创建新的实例,适合轻量级、无状态的服务,或者每次调用都需要新实例的场景。我得让用户明白,虽然每次创建新实例,但对于无状态的服务来说,这并不会带来性能问题。

五、依赖注入的方式

依赖注入三种方式

  1. 构造函数注入
    构造函数注入是最常见和推荐的依赖注入方式。通过构造函数注入,类的依赖项在创建实例时通过构造函数参数传递。
public class OrderService
{private readonly IOrderRepository _orderRepository;private readonly ILogger<OrderService> _logger;public OrderService(IOrderRepository orderRepository, ILogger<OrderService> logger){_orderRepository = orderRepository;_logger = logger;}public void ProcessOrder(Order order){_logger.LogInformation("Processing order: {OrderId}", order.Id);_orderRepository.SaveOrder(order);}
}

优点:确保对象在创建时所有依赖项都已就绪。
缺点:对于具有许多依赖项的类,构造函数可能会变得臃肿。
2. 属性注入
属性注入通过设置类的属性来注入依赖项。这种方式适用于可选依赖项或配置。

public class ReportGenerator
{public IExportService ExportService { get; set; }public INotificationService NotificationService { get; set; }public ReportGenerator(){}public void GenerateAndExportReport(){var report = GenerateReport();ExportService.Export(report);NotificationService.SendNotification("Report generated and exported.");}
}

优点:允许在对象创建后动态设置依赖项。
缺点:依赖项可能在使用前未被设置,导致运行时错误。
3. 方法注入
方法注入通过方法参数传递依赖项。这种方式适用于临时依赖项或方法级别的依赖。

public class ReportService
{public void GenerateReport(IReportTemplate template){template.ApplyFormatting();}
}

优点:适用于短期或方法级别的依赖项。
缺点:每次调用方法都需要传递依赖项,可能导致代码重复。
4.总结
构造函数注入:最适合大多数场景,确保对象创建时依赖项就绪。
属性注入:适用于可选依赖项或配置。
方法注入:适用于临时或方法级别的依赖项。

http://www.xdnf.cn/news/14712.html

相关文章:

  • 【ad-hoc】# P12414 「YLLOI-R1-T3」一路向北|普及+
  • MyBatis批量删除
  • 现代 JavaScript (ES6+) 入门到实战(一):告别 var!拥抱 let 与 const,彻底搞懂作用域
  • 数据结构笔记4:数组、链表OJ
  • 华为云 Flexus+DeepSeek 征文|华为云 Flexus 云服务 Dify-LLM 平台深度部署指南:从基础搭建到高可用实践
  • 疏通经脉: Bridge 联通逻辑层和渲染层
  • 使用component封装组件和h函数的用法
  • 数据结构之Map和Set
  • 打造地基: App拉起基础小程序容器
  • linux面试常考
  • 正交视图三维重建 笔记 2d线到3d线
  • 使用deepseek制作“喝什么奶茶”随机抽签小网页
  • Jina-Embeddings-V4:多模态向量模型的革命性突破与实战指南
  • Python生成器表达式最佳实践指南:何时使用与高效选择
  • Flutter基础(控制器)
  • Python基础(吃洋葱小游戏)
  • LINUX628 NFS 多web;主从dns;ntp;samba
  • WOE值:风险建模中的“证据权重”量化术——从似然比理论到FICO评分卡实践
  • SpringMVC系列(五)(响应实验以及Restful架构风格(上))
  • H6-108QB2W QILSTE/旗光
  • WebRTC(十二):DTLS
  • Cesium快速入门到精通系列教程十一:Cesium1.74中高性能渲染上万Polyline
  • 2025第十五届上海生物发酵展:江苏健达干燥盛装赴会
  • 数据结构:最小生成树—Prim(普里姆)与Kruskal(克鲁斯卡尔)算法
  • 使用asyncio构建高性能网络爬虫
  • Linux离线搭建Redis (centos7)详细操作步骤
  • Python助力自动驾驶:深度学习模型优化全攻略
  • Flutter基础(Riverpod)
  • 用AI给AR加“智慧”:揭秘增强现实智能互动的优化秘密
  • 【学习笔记】深入理解Java虚拟机学习笔记——第12章 Java内存模型与线程