public static IServiceCollection CreateChildContainer()

in src/WebJobs.Script.WebHost/DependencyInjection/ServiceProviderExtensions.cs [36:143]


        public static IServiceCollection CreateChildContainer(this IServiceProvider serviceProvider, IServiceCollection serviceCollection)
        {
            IServiceCollection clonedCollection = new ServiceCollection();
            var servicesByType = serviceCollection.GroupBy(s => s.ServiceType);

            foreach (var services in servicesByType)
            {
                if (ChildContainerIgnoredTypes.Contains(services.Key))
                {
                    // Do nothing - we don't want to copy these to a child scope for reasons above
                }

                // A generic type definition is rather used to create other constructed generic types.
                else if (services.Key.IsGenericTypeDefinition)
                {
                    // So, we just need to pass the descriptor.
                    foreach (var service in services)
                    {
                        clonedCollection.Add(service);
                    }
                }

                // If only one service of a given type.
                else if (services.Count() == 1)
                {
                    var service = services.First();

                    if (service.Lifetime == ServiceLifetime.Singleton)
                    {
                        // An host singleton is shared across tenant containers but only registered instances are not disposed
                        // by the DI, so we check if it is disposable or if it uses a factory which may return a different type.

                        if (typeof(IDisposable).IsAssignableFrom(service.GetImplementationType()) || service.ImplementationFactory != null)
                        {
                            // If disposable, register an instance that we resolve immediately from the main container.
                            clonedCollection.CloneSingleton(service, serviceProvider.GetService(service.ServiceType));
                        }
                        else
                        {
                            // If not disposable, the singleton can be resolved through a factory when first requested.
                            clonedCollection.CloneSingleton(service, _ => serviceProvider.GetService(service.ServiceType));

                            // Note: Most of the time a singleton of a given type is unique and not disposable. So,
                            // most of the time it will be resolved when first requested through a tenant container.
                        }
                    }
                    else
                    {
                        clonedCollection.Add(service);
                    }
                }

                // If all services of the same type are not singletons.
                else if (services.All(s => s.Lifetime != ServiceLifetime.Singleton))
                {
                    // We don't need to resolve them.
                    foreach (var service in services)
                    {
                        clonedCollection.Add(service);
                    }
                }

                // If all services of the same type are singletons.
                else if (services.All(s => s.Lifetime == ServiceLifetime.Singleton))
                {
                    // We can resolve them from the main container.
                    // Materialize services and instances to arrays once.
                    var servicesArray = services.ToArray();
                    var instancesArray = serviceProvider.GetServices(services.Key)?.ToArray() ?? Array.Empty<object>();

                    // Validate counts
                    ValidateServiceAndInstanceCounts(servicesArray, instancesArray, services.Key);

                    for (var i = 0; i < servicesArray.Length; i++)
                    {
                        clonedCollection.CloneSingleton(servicesArray[i], instancesArray[i]);
                    }
                }

                // If singletons and scoped services are mixed.
                else
                {
                    // We need a service scope to resolve them.
                    using var scope = serviceProvider.CreateScope();

                    // Materialize services and instances to arrays once.
                    var servicesArray = services.ToArray();
                    var instancesArray = scope.ServiceProvider.GetServices(services.Key)?.ToArray() ?? Array.Empty<object>();

                    ValidateServiceAndInstanceCounts(servicesArray, instancesArray, services.Key);

                    // Then we only keep singleton instances.
                    for (var i = 0; i < servicesArray.Length; i++)
                    {
                        if (servicesArray[i].Lifetime == ServiceLifetime.Singleton)
                        {
                            clonedCollection.CloneSingleton(servicesArray[i], instancesArray[i]);
                        }
                        else
                        {
                            clonedCollection.Add(servicesArray[i]);
                        }
                    }
                }
            }

            return clonedCollection;
        }