勇哥注:
依赖注、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("文件存储成功");
}
}
}


少有人走的路


















