这个系列已经写了5篇,链接地址如下:
如果想对本篇有个更好的了解,建议需要先看
“[Asp.net 5] DependencyInjection项目代码分析”
“[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(1)”
“[Asp.net 5] DependencyInjection项目代码分析4-微软的实现(2)”。
在之前的“上“、”中“俩篇已经介绍了ServiceTable、IGenericService、IService、IServiceCallSite、ServiceEntry、GenericService、InstanceService、FactoryService、Service等类。本节主要介绍核心的”ServiceProvider“类。
IServiceProvider类
IServiceProvider类是微软这套DependencyInjection中直接对外的接口。而ServiceProvider是直接实现IServiceProvider并且对外直接提供功能的核心类。
对于ServiceProvider不仅要能够获取注入的类,还需要根据不同定义的范围获取不同范围的注入类。对于不同的范围(Transient、Scoped、Singleton),ServiceProvider需要使用不同的逻辑。我们简单分析下。
- 对于Transient,每次都创建一个新的实例,所以代码中只需直接创建该注入类的实例即可,不需要对该类进行缓存;
- 对于Singleton,全局只有一个实例,代码中可以将创建的对象缓存到静态的字典表中,之后每次需要该类型实例首先到全局静态字典表中去查找如果存在则直接返回,不存在创建后加入到字典表中,之后返回。(实际上源码中并未缓存到全局变量中,具体实现方式后面会讲解)
- 对于Scoped,每个Scope内是唯一的,不同Scope范围是不同的。这个就比较难实现。不过我们可以通过外部调用的代码简单的猜测下,之后我们通过查看源代码进行验证。
下面是不同Scoped范围的代码调用。
public void ScopedServiceCanBeResolved() { IServiceProvider container = CreateContainer(); var scopeFactory = container.GetService<IServiceScopeFactory>(); using (var scope = scopeFactory.CreateScope()) { var containerScopedService = container.GetService<IFakeScopedService>(); var scopedService1 = scope.ServiceProvider.GetService<IFakeScopedService>(); var scopedService2 = scope.ServiceProvider.GetService<IFakeScopedService>(); Assert.NotEqual(containerScopedService, scopedService1); Assert.Equal(scopedService1, scopedService2); } } [Fact] public void NestedScopedServiceCanBeResolved() { IServiceProvider container = CreateContainer(); IServiceScopeFactory outerScopeFactory = container.GetService<IServiceScopeFactory>(); using (var outerScope = outerScopeFactory.CreateScope()) { var innerScopeFactory = outerScope.ServiceProvider.GetService<IServiceScopeFactory>(); using (var innerScope = innerScopeFactory.CreateScope()) { var outerScopedService = outerScope.ServiceProvider.GetService<IFakeScopedService>(); var innerScopedService = innerScope.ServiceProvider.GetService<IFakeScopedService>(); Assert.NotEqual(outerScopedService, innerScopedService); } } }