依赖注入
依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。
两种实现方式:
1)服务定位器(ServiceLoccator);
2)依赖注入(Dependency Injection,DI)
DI相关概念
1)服务(Service):对象 即使用者需要的内容;
2)注册服务:服务与其实现的关系;
3)服务容器:负责管理注册的服务;
4)查询服务:创建对象;
5)对象声明周期:Transient(瞬态);Scoped(范围);Singleton(单例);
.Net中使用DI(概念)
1)根据类型来注册和获取服务,可以分别指定服务类型(Service Type)和实现类型(Implementation Type)。这两者可能相同,也可能不同。服务类型可以是具体的实现类,也可以是接口,建议面向接口编程。
2).NET控制反转组件名称为:DependencyInjection,它包含ServiceLocator的功能。
.Net中使用DI(实现)
1)安装对应包并引用,Install-Package Microsoft.Extensions.DependencyInjection
2)ServiceCollection用来构造容器对象IServiceProvider。 具体调用ServiceCollection的BuildServiceProvider方法。可以用来获取调用BuildServiceProvider之前已注册的服务。

using System; using Microsoft.Extensions.DependencyInjection; namespace ConsoleApp1 { internal class Program { static void Main(string[] args) { var services = new ServiceCollection();//创建服务集合 services.AddScoped<TestServiceImp1>();//注册一个瞬态服务 services.AddScoped<ITestService, TestServiceImp2>();//以接口、服务类型的方式注册 方式1 //services.AddScoped(typeof(ITestService), typeof(TestServiceImp2));//以接口、服务类型的方式注册 方式2 using (var serviceProvider = services.BuildServiceProvider())//创建一个服务提供者 { var testservice = serviceProvider.GetService<TestServiceImp1>(); testservice.SayHi(); } } } public interface ITestService { public string Name { get; set; } public void SayHi(); } public class TestServiceImp1 : ITestService { public string Name { set; get; } public void SayHi() { Console.WriteLine($"hi,I am {Name}"); } } public class TestServiceImp2 : ITestService { public string Name { set; get; } public void SayHi() { Console.WriteLine($"你好,我是{Name}"); } } }
例子2
using System;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
IServiceCollection services = new ServiceCollection();
//方法1:万能公式 其它的都是扩展方法,本质调用的还是这个万能公式,包括委托的方式(他的实现类型是一个委托)
services.Add(new ServiceDescriptor(typeof(ISerivce), typeof(Service), ServiceLifetime.Singleton));
//方法2:泛型接口
services.AddSingleton<ISerivce, Service>();
//方法3:反射接口 反射的方式在编写框架时十分有用,无反射无框架
services.AddSingleton(typeof(ISerivce), typeof(Service));
//方法4:委托方式 当我们构建的对象需要编写逻辑时,委托方式十分有用
services.AddSingleton<IDbConnection>(sp =>
{
//获取参数逻辑
return new DbConnection("127.0.0.1");
});
//方法5:泛型注册 注册泛型时,只能使用反射接口,并且泛型参数不要写入,解析时来确立,如果有多个泛型参数使用逗号隔开
services.AddSingleton(typeof(ILogger<>), typeof(ConsoleLogger<>));
var con = services.BuildServiceProvider();
var service1 = con.GetRequiredService<ISerivce>();
var service2 = con.GetRequiredService<IDbConnection>();
var service3 = con.GetRequiredService<ILogger<DbConnection>>();
}
}
public interface ISerivce
{ }
public class Service : ISerivce
{ }
public interface IDbConnection
{ }
public class DbConnection : IDbConnection
{
public DbConnection(string connectionStr)
{
Console.WriteLine($"use {connectionStr} connect succeed!");
}
}
public interface ILogger<T>
{ }
public class ConsoleLogger<T> : ILogger<T>
{
public ConsoleLogger()
{
Console.WriteLine($"T is {typeof(T)}");
}
}
}
IServiceProvider的服务定位器常用方法
1)T T? GetService<T>() 如获取不到对象,则返回Null
2)objcet GetService(Type serviceType) 一般搭配反射使用
3)T GetRequiredService<T>() 如果获取不到对象,则抛出异常
4)objcet GetRequiredService(Type serviceType)
5)IEnumerable<T> GetServices<T>() 适用于一个服务类型有多个实现对象
6)IEnumerable<object?> GetServices(Type serviceType)