[Dot Net Core](Graphic series )2. IOC - An important part of system design-an overview of preparations

Czxdas
4 min readJan 3, 2022

Dot Net Core has many mechanisms that will use DI, even when the Host is going to be built, it will often be used. And external related kits often use this mechanism to design; whether it is kits or self-developed, IOC will become an important part of the design.

The following will give an overview of the process of Host preparing the DI mechanism. First see ServiceProviderFactory :

ServiceProviderFactory in HostBuilder

Initially, in Program.Main, call the CreateHostBuilder method of the static category Host, add a HostBuilder entity, then call the extension method UseDefaultServiceProvider, add a ServiceFactoryAdapter entity, and set the _contextResolver and _factoryResolver in the entity as delegate settings. Finally, reference the _serviceProviderFactory of HostBuilder to the ServiceFactoryAdapter entity.

HostBuilder -> Build -> CreateServiceProvider

Next is the CreateServiceProvider part mentioned in the previous “Operation Overview Diagram”. When HostBuilder executes the Build action, the fifth step, CreateServiceProvider, processes the set of delegated events in _configureServiceActions, one of which is to add a Startup category entity, and then run its ConfigureServices method. This method provides the author with the opportunity to specify the relevant IOC preparations and store these DI settings in the ServiceCollection.

After setting the registered DI, use HostBuilder._serviceProviderFactory to add a Provider containing ServiceCollection information and assign it to HostBuilder._appServices.

As mentioned earlier, the _serviceProviderFactory of the Host refers to the ServiceFactoryAdapter entity, so calling _serviceProviderFactory.CreateBuilder is actually calling ServiceFactoryAdapter.CreateBuilder. This is mainly to explain that the ServiceFactoryAdapter will use the delegated _contextResolver and _factoryResolver to generate the DefaultServiceProviderFactory entity.

The following will track in detail how the ServiceFactoryAdapter converts the DefaultServiceProviderFactory, and further build the registered ServiceCollection data into the ServiceProviderEngine to become the final DI engine of the .NET Core IOC.

ServiceProviderEngine

ServiceCollection uses the extension method to register the service in the collection of the ServiceDescriptor type. ServiceDescriptor stores registration-related information such as what type of type, how to generate entities, what kind of life cycle, etc. In other words, according to Methods such as AddSingleton, AddScoped, AddTransient, Add, etc., determine how or whether to give values for its ImplementationType, ImplementationInstance, and ImplementationFactory. ServiceCollection also has another extension method, BuildServiceProvider, which will generate DynamicServiceProviderEngin, which inherits ServiceProvider. This Provider contains an extremely important engine, ServiceProviderEngine. The engine will use the CallSiteFactory to find the corresponding callSite, which affects the content executed when the corresponding entity is generated by the subsequent DI.

The Provider will finally be assigned to the _appServices of the HostBuilder, which can provide GetService. After the Type of DI to be implemented is passed in, the entity can be generated from the information it just prepared.

GetService decides what method to execute to generate entities. It is collected when the service is registered and registered in the ServiceDescriptor, all of which are in the information in system.type.
Finally, when the ServiceCallSite is obtained in GetService, the corresponding type of callSite (ConstantCallSite, FactoryCallSite, ConstructorCallSite) is generated after the judgment of this information
Type.GetTypeInfo() You can see whether the relevant information includes whether there is a constructor, what methods, public or private, and component information are included.

ServiceProvider and DynamicServiceProviderEngine

The figure above shows the correlation diagram between ServiceProvider and DynamicServiceProviderEngine. ServiceProvider._engine is DynamicServiceProviderEngine, and DynamicServiceProviderEngine contains CallSiteFactory. This object will store the CallSite required by the registered service. If it has ever been generated, it will be temporarily stored in the _callSiteCache collection. How CallSiteFactory generates the corresponding CallSite will inevitably use the information registered in the ServiceCollection.

After the DynamicServiceProviderEngine successfully obtains the corresponding CallSite, it finally uses the RuntimeResolver to generate the corresponding entity.

In the relationship between ServiceProvider and DynamicServiceProviderEngine in the above figure, there is an inherited category called CompiledServiceProviderEngine. This is an extra detail, pointing out that ServiceProviderEngine actually runs RuntimeResolver through ILEmitResolverBuilder.

In the future, I will show how actually the MVC Controller category of .Net Core performs DI. Here is a little hint:

To generate MVC Controller type entities, the information of ControllerActionInvoker and ControllerContext is mainly used, and the CreateControllerFactory method is called through ControllerFactoryProvider.

Then run the GetService of ServiceProviderEngineScope, and the entity is generated as described in the previous pictures.

Dot Net Core needs to implement DI, In fact, there are some complicated processes, but in this section, we will get a general understanding. When we explain other processes later, we can refer to DI (GetService), so we don’t need to repeat it!

--

--