勇哥注:
依赖注、IoC容器、控制反转这些,勇哥已经发过许多贴子。下面这些供大家参考:
控制反转思想,来自生活与编程等各方面的例子
依赖倒置(反转)(DIP),控制反转(IoC),依赖注入(DI),IoC容器
载自知乎一篇非常好的介绍依赖倒置原则的文章
依赖注入 和 new 一个实例有什么区别吗?
依赖注入,在.net framework时,我们用得较多的是Unity,这个最早是微软维护的,后来变成社区维护。
这个东西比较牛,除了支持IoC,还支持aop。
在.net Core的时代,微软提供的官方ioc包就是本文要介绍的这个 Microsoft.Extensions.DependencyInjection
DI的一些基本概念
服务(service):对象;
注册服务;
服务容器:负责管理注册的服务
查询服务:创建对象及关联对象
对象生命周期:Transient(瞬态);Scoped(范围);Singleton(单例);
.NET中使用DI
根据类型来获取和注册服务
可以分别指定服务类型(service type)和实现类型( implementation type)。
这两者可能相同,也可能不同。
服务类型可以是类,也可以是接口,建议面向接口编程,更加灵活。
.NET的控制反转组件叫DependencyInjection,但它包含ServiceLocator的功能。
包名字叫: Microsoft.Extensions.DependencyInjection
使用流程:
ServiceCollection用来构造容器对象IServiceProvider。调用ServiceCollection的
BuildServiceProvider() 创建的 ServiceProvider,可以用来获取BuildServiceProvider()
之前ServiceCollection中的对象。
源码,服务定位器模式(ServiceLocator):
using Microsoft.Extensions.DependencyInjection; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { ServiceCollection services = new ServiceCollection(); services.AddTransient<TestService1>(); using(ServiceProvider serviceProvider = services.BuildServiceProvider()) { var testService = serviceProvider.GetService<TestService1>(); testService.Name= "刘备"; testService.SayHi(); } } } public interface ITestService { public string Name { get; set; } public void SayHi(); } public class TestService1 : ITestService { public string Name { get; set; } public void SayHi() { Console.WriteLine($"Hi,I'm {Name}"); } } public class TestService2 : ITestService { public string Name { get; set; } public void SayHi() { Console.WriteLine($"你好,我是 {Name}"); } } }
源码,基于构造函数的DI注入方式 :
using Microsoft.Extensions.DependencyInjection; using System.Security.Authentication.ExtendedProtection; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { IServiceCollection services = new ServiceCollection(); services.AddScoped<MyController,MyController>(); services.AddScoped<ILog,MyLog>(); services.AddScoped<IConfig,MyConfig>(); services.AddScoped<IStorage,MyStorage>(); //services.AddScoped(typeof(MyController), typeof(MyController)); //services.AddScoped(typeof(ILog), typeof(MyLog)); //services.AddScoped(typeof(IConfig), typeof(MyConfig)); //services.AddScoped(typeof(IStorage), typeof(MyStorage)); ServiceProvider sp=services.BuildServiceProvider(); using(IServiceScope is1=sp.CreateScope()) { MyController? con =is1.ServiceProvider.GetService<MyController>(); con?.Test(); } } } public class MyController { private readonly ILog log; private readonly IConfig config; private readonly IStorage storage; public MyController(ILog log, IConfig config, IStorage storage) { this.log = log; this.config = config; this.storage = storage; } public void Test() { log.Log($"读取配置[{config.Read("path")}]"); log.Log("开始连接数据库"); storage.Save(); log.Log("关闭数据库连接"); } } public interface ILog { void Log(string message); } public class MyLog : ILog { public void Log(string message) { Console.WriteLine(message); } } public interface IConfig { string Read(string message); } public class MyConfig : IConfig { public string Read(string message) { return $"从文件读取的配置项[{message}]"; } } public interface IStorage { void Save(); } public class MyStorage : IStorage { public void Save() { Console.WriteLine("文件存储成功"); } } }

