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)

這不是它的工作方式!

這個 ConcurrentDictionaryServiceTable 的屬性,這是 ServiceProvider 的屬性