返回 C#常用知识小短篇

.NET的DI框架

以下为完整正文内容。

正文

框架总共做三件事: 1.存储:告诉框架有哪些东西 2.创建:告诉框架怎么创建东西 3.发出:有调用需求就发出 直接看例子🌰 // ServiceCollection 就是容器 var services = new ServiceCollection(); // 往里面存东西(注册) services.AddSingleton<Config>(); services.AddScoped<IUserService, UserService>(); // 建好容器 var provider = services.BuildServiceProvider(); // 从里面拿东西(注入) var config = provider.GetService<Config>(); ServiceCollection就是仓库(容器) ServiceProvider 负责发送 无注释代码: var services = new ServiceCollection(); services.AddSingleton<Config>(); services.AddScoped<IUserService, UserService>(); var provider = services.BuildServiceProvider(); var config = provider.GetService<Config>(); 三种生命周期: // Singleton:整个程序只有一个 services.AddSingleton<Config>(); // 任何时候拿,都是同一个实例 // Scoped:一个请求(周期)内共享同一个实例 services.AddScoped<IUserService, UserService>(); // 同一个请求(周期)内拿多次,是同一个实例 // 不同请求则是不同的实例 // Transient:每次都要新的 services.AddTransient<IEmailService, EmailService>(); // 每次注入都新建一个实例 无注释: services.AddSingleton<Config>(); services.AddScoped<IUserService, UserService>(); services.AddTransient<IEmailService, EmailService>(); 注册方式有以下几类 // 注册具体类 services.AddSingleton<MyService>(); // 注册接口→实现类 services.AddScoped<IMyService, MyService>(); // 注册时用工厂方法 services.AddSingleton(sp => new MyService("参数")); // 注册实例 var config = new Config(); services.AddSingleton<Config>(config); // Options 扩展 services.AddOptions().Configure<Config>(...); ——注入方式—— 构造函数注入(最常用)可以说会这个就行了 //继承Controller因为它提供了控制器需要的所有内置功能 public class TestController : Controller { private readonly IOptionsSnapshot<Config> _config; private readonly ILogger<TestController> _logger; // 在构造函数参数里声明要什么 public TestController(IOptionsSnapshot<Config> config, ILogger<TestController> logger) { _config = config; _logger = logger; } } 方法注入 // Minimal API 里最常见 app.MapGet("/config", (IOptionsSnapshot<Config> config) => { return config.Value; }); // 也可以多个依赖 app.MapPost("/user", (IUserService userService, ILogger<Program> logger, UserDto dto) => { logger.LogInformation("创建用户"); return userService.Create(dto); }); 手动注入(能工智人)能不用就不用 // 从 ServiceProvider 手动取 var provider = services.BuildServiceProvider(); var config = provider.GetService<IOptions<Config>>(); // 或者在一段代码里临时需要 public void SomeMethod(IServiceProvider sp) { var logger = sp.GetRequiredService<ILogger>(); logger.LogInformation("临时用一下"); } 看一个完整的综合例子 using Microsoft.Extensions.DependencyInjection; class Program { static void Main(string[] args) { // 创建容器 var services = new ServiceCollection(); //注册服务 // 注册具体类 services.AddSingleton<Calculator>(); // 注册接口→实现 services.AddScoped<ILogger, ConsoleLogger>(); // 注册接口→实现 services.AddTransient<IEmailSender, EmailSender>(); // 注册时用 Lambda 工厂 services.AddSingleton(sp => new Config("程序名称", "1.0")); // 构建容器 var provider = services.BuildServiceProvider(); // 从现在起可以使用了 // 手动获取 var config = provider.GetService<Config>(); Console.WriteLine($"程序:{config.Name} v{config.Version}"); // 获取服务(自动填充依赖) var calc = provider.GetService<Calculator>(); calc.Add(10, 5); calc.Subtract(10, 5); } } public class Config { public string Name { get; set; } public string Version { get; set; } public Config(string name, string version) { Name = name; Version = version; } } public interface ILogger { void Log(string msg); } public class ConsoleLogger : ILogger { public void Log(string msg) { Console.WriteLine($"[日志] {msg}"); } } public interface IEmailSender { void Send(string to, string body); } public class EmailSender : IEmailSender { public void Send(string to, string body) { Console.WriteLine($"发送邮件给 {to}:{body}"); } } public class Calculator { private readonly ILogger _logger; private readonly IEmailSender _sender; // 构造函数注入 public Calculator(ILogger logger, IEmailSender sender) { _logger = logger; _sender = sender; } public void Add(int a, int b) { int result = a + b; _logger.Log($"{a} + {b} = {result}"); } public void Subtract(int a, int b) { int result = a - b; _sender.Send("admin@qq.com", $"{a} - {b} = {result}"); } } 运行结果: 程序:程序名称 v1.0 [日志] 10 + 5 = 15 发送邮件给 admin@qq.com:10 - 5 = 5