依赖注入
基本概念
依赖注入(Dependency Injection,DI)是控制反转(Inversion of Control,IOC)思想的实现方式。依赖注入简化模块的组装过程,降低模块之间的耦合度。
依赖注入中对象的声明周期:
瞬态(Transient):每次获取服务,都会创建一个新的对象;
范围(Scoped):某个范围内,获取到的都是同一个对象,但是出了这个范围,获取到的就是新对象;
单例(Singleton):在全局获取服务,获取到的都是同一个对象;
生命周期的使用
三种生命周期的使用场景:
如果 类无状态,建议使用
Singleton
;如果 类有状态,且有 Scope 控制,建议为
Scoped
,因为通常这种 Scoped 控制下的代码都是运行在同一个线程中,没有并发修改的问题;瞬态不建议使用;
写代码之前,请先安装
Microsoft.Extensions.DependencyInjection
这个 Nuget 包。
瞬态
C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为瞬态服务
services.AddTransient<TestServiceImpl>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
t.Name = "sunny";
t.SayHi();
TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
Console.WriteLine(object.ReferenceEquals(t1, t2)); //false,说明t1和t2是两个对象
}
范围
C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为范围
services.AddScoped<TestServiceImpl>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
using (IServiceScope scope = sp.CreateScope())
{
TestServiceImpl t1 = scope.ServiceProvider.GetService<TestServiceImpl>();
TestServiceImpl t2 = scope.ServiceProvider.GetService<TestServiceImpl>();
Console.WriteLine(object.ReferenceEquals(t1, t2)); // true,说明Scoped在using范围内是同一个对象
}
}
单例3
C#
ServiceCollection services = new ServiceCollection();
// 将 TestServiceImpl 声明为单例
services.AddSingleton<TestServiceImpl>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
t1.Name = "sunny";
t1.SayHi();
TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
t2.Name = "TOM";
t2.SayHi();
t1.SayHi(); // TOM
Console.WriteLine(object.ReferenceEquals(t1, t2)); // true:t1和t2指向同一个地址,说明是在全局创建了一个对象
}
ServiceProvider()
ServiceProvider
类继承自 IServiceProvider,也可以当作是 IServiceProvider 的方法:
方法 | 作用 |
---|---|
GetService<T>() | 获取服务中的对象,若没有获取到,则返回null |
GetService(Type serviceType) | 同上 |
GetRequiredService<T>() | 获取服务中的对象,若没有获取到,则直接报错 |
GetRequiredService(Type serviceType) | 同上 |
GetServices<T>() | 获取多个服务中的对象 |
C#
ServiceCollection services = new ServiceCollection();
services.AddScoped<ITestService, TestServiceImpl>();
services.AddScoped<ITestService, TestServiceImpl2>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
// GetService获取服务中的对象,若没有获取到,则返回null
ITestService t1 = sp.GetService<ITestService>();
ITestService t2 = (ITestService)sp.GetService(typeof(ITestService));
// GetRequiredService获取服务中的对象,若没有获取到,则直接报错
ITestService t3 = sp.GetRequiredService<ITestService>();
ITestService t4 = (ITestService)sp.GetRequiredService(typeof(ITestService));
// GetServices获取多个服务中的对象
IEnumerable<ITestService> t5 = sp.GetServices<ITestService>();
foreach (ITestService item in t5)
{
Console.WriteLine(item.GetType());
}
}