Microsoft.Extensions.DependencyInjection 的内部工作方式
IServiceCollection
要开始使用 Microsoft 的 DI nuget 包构建 IOC 容器,首先要创建一个 IServiceCollection
。你可以使用已经提供的 Collection:ServiceCollection
:
var services = new ServiceCollection();
这个 IServiceCollection
只不过是一个实现:IList<ServiceDescriptor>, ICollection<ServiceDescriptor>, IEnumerable<ServiceDescriptor>, IEnumerable
以下所有方法都只是将 ServiceDescriptor
实例添加到列表中的扩展方法:
services.AddTransient<Class>(); //add registration that is always recreated
services.AddSingleton<Class>(); // add registration that is only created once and then re-used
services.AddTransient<Abstract, Implementation>(); //specify implementation for interface
services.AddTransient<Interface>(serviceProvider=> new Class(serviceProvider.GetService<IDependency>())); //specify your own resolve function/ factory method.
services.AddMvc(); //extension method by the MVC nuget package, to add a whole bunch of registrations.
// etc..
//when not using an extension method:
services.Add(new ServiceDescriptor(typeof(Interface), typeof(Class)));
IServiceProvider
serviceprovider 是’Compiling’的所有注册,以便它们可以快速使用,这可以通过 services.BuildServiceProvider()
完成,这基本上是一个扩展 mehtod:
var provider = new ServiceProvider( services, false); //false is if it should validate scopes
在幕后,IServiceCollection
中的每个 ServiceDescriptor
都被编译为工厂方法 Func<ServiceProvider, object>
,其中 object 是返回类型,它是:Implementation 类型的创建实例,Singleton 或你自己定义的工厂方法。
这些注册被添加到 ServiceTable
,它基本上是一个 ConcurrentDictionary
,其关键是 ServiceType
和上面定义的 Factory 方法的值。
结果
现在我们有一个 ConcurrentDictionary<Type, Func<ServiceProvider, object>>
,我们可以同时使用它来请求为我们创建服务。展示一个如何看待它的基本例子。
var serviceProvider = new ConcurrentDictionary<Type, Func<ServiceProvider, object>>();
var factoryMethod = serviceProvider[typeof(MyService)];
var myServiceInstance = factoryMethod(serviceProvider)
这不是它的工作方式!
这个 ConcurrentDictionary
是 ServiceTable
的属性,这是 ServiceProvider
的属性