参考:
https://www.cnblogs.com/zoro-zero/p/13490459.html
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1
DI:是一种软件设计模式,Asp.net core支持该模式。这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。
依赖项:指另一个对象所依赖的对象。
常见的DI框架:Autofac、Unity......
依赖关系注入概述—— 谁依赖谁,将谁注入谁
依赖注入是指在创建一个对象时,自动地创建它所依赖的对象,并注入。
依赖注入的方式:1.构造方法注入; 2.Set方法注入; 3.方法参数注入
1.构造方法注入:
优点:
- 在构造方法中体现出对其他类的依赖,直接就可以看出这个类所需要的依赖那些类才能工作。
- 脱离了IOC框架,这个类仍然可以工作。
- 一旦对象初始化成功了,这个对象的状态肯定是正确的。
缺点:
- 构造函数会有很多参数(Bad smell)。
- 有些类是需要默认构造函数的,比如MVC框架的Controller类,一旦使用构造函数注入,就无法使用默认构造函数。
- 这个类里面的有些方法并不需要用到这些依赖(Bad smell)。
2.Set方法注入
- 在对象的整个生命周期内,可以随时动态的改变依赖。
- 非常灵活。
- 对象在创建后,被设置依赖对象之前这段时间状态是不对的。
- 不直观,无法清晰地表示哪些属性是必须的。
3.方法参数注入--即以入参的方法,将对象赋值给方法内的对象
方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。类似如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public class MovieRecommender { private MovieCatalog movieCatalog; public class MovieRecommender { private MovieCatalog movieCatalog; private CustomerPreferenceDao customerPreferenceDao; @Autowired public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) { this .movieCatalog = movieCatalog; this .customerPreferenceDao = customerPreferenceDao; } // ... } private CustomerPreferenceDao customerPreferenceDao; public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) { this .movieCatalog = movieCatalog; this .customerPreferenceDao = customerPreferenceDao; } // ... } |
- 比较灵活。
- 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦。
- 与构造方法注入一样,会有很多参数。
依赖注入使用注意事项:
1.使用接口或基类将依赖关系实现抽象化
2.在服务容器中注册依赖关系。 ASP.NET Core 提供了一个内置的服务容器 IServiceProvider。 服务通常已在应用的 Startup.ConfigureServices
方法中注册。
3.将服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。
如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | using System; namespace Models { public interface IMyDependency { void WriteMessage( string message); } } using System; namespace Models { /// <summary> /// 示例应用使用具体类型 MyDependency 注册 IMyDependency 服务 /// </summary> public class MyDependency : IMyDependency { /// <summary> /// 传参注入 /// </summary> /// <param name="message">依赖项</param> public void WriteMessage( string message) { Console.WriteLine($ "MyDependency.WriteMessage Message: {message}" ); } } }注:以上示例应用使用具体类型 MyDependency 注册 IMyDependency 服务; AddScoped 方法使用范围内生存期(单个请求的生存期)注册服务 public void ConfigureServices(IServiceCollection services) { services.AddScoped<IMyDependency, MyDependency>(); services.AddRazorPages(); }在示例应用中,请求 IMyDependency 服务并用于调用 WriteMessage 方法: namespace Models.Model.Demo1 { public class OneModel { private readonly IMyDependency _myDependency; public OneModel(IMyDependency myDependency) { _myDependency = myDependency; } public void OnGet() { _myDependency.WriteMessage( "OneModel.OnGet" ); } } } namespace Models.Model.Demo1 { public class MyDependency2 : IMyDependency { private readonly ILogger<MyDependency2> _logger; /// <summary> /// 构造注入 /// </summary> /// <param name="logger">依赖项</param> public MyDependency2(ILogger<MyDependency2> logger) { _logger = logger; } /// <summary> /// 传参注入 /// </summary> /// <param name="message">依赖项</param> public void WriteMessage( string message) { _logger.LogInformation($ "MyDependency2.WriteMessage Message: {message}" ); } } } |
通过使用 DI 模式,表示控制器:
- 不使用具体类型
MyDependency
,仅使用它实现的IMyDependency
接口。 这样可以轻松地更改控制器使用的实现,而无需修改控制器。 - 不创建
MyDependency
的实例,这由 DI 容器创建。
可以通过使用内置日志记录 API 来改善 IMyDependency
接口的实现:using Microsoft.Extensions.Logging;
更新的 ConfigureServices 方法注册新的 IMyDependency 实现: public void ConfigureServices(IServiceCollection services) { services.AddScoped<IMyDependency, MyDependency2>(); } MyDependency2 依赖于 ILogger<TCategoryName>,并在构造函数中对其进行请求。 ILogger<TCategoryName> 是框架提供的服务
1 | 必须被解析的依赖关系的集合通常被称为“依赖关系树”、“依赖关系图”或“对象图” |
容器通过利用(泛型)开放类型解析 ILogger<TCategoryName>
,而无需注册每个(泛型)构造类型。
在依赖项注入术语中,服务:
- 通常是向其他对象提供服务的对象,如
IMyDependency
服务。 - 与 Web 服务无关,尽管服务可能使用 Web 服务。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
2020-11-24 C# 后端调用 Web API