Skip to content

Commit e7ab800

Browse files
Adding check for service and instances count. (#10741)
* Adding check for service and instances count.
1 parent 30cafb8 commit e7ab800

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

src/WebJobs.Script.WebHost/DependencyInjection/ServiceProviderExtensions.cs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System;
88
using System.Collections.Generic;
99
using System.Linq;
10+
using System.Text;
1011
using Microsoft.AspNetCore.Hosting;
1112
using Microsoft.Extensions.DependencyInjection;
1213
using Microsoft.Extensions.Hosting;
@@ -98,11 +99,16 @@ public static IServiceCollection CreateChildContainer(this IServiceProvider serv
9899
else if (services.All(s => s.Lifetime == ServiceLifetime.Singleton))
99100
{
100101
// We can resolve them from the main container.
101-
var instances = serviceProvider.GetServices(services.Key);
102+
// Materialize services and instances to arrays once.
103+
var servicesArray = services.ToArray();
104+
var instancesArray = serviceProvider.GetServices(services.Key)?.ToArray() ?? Array.Empty<object>();
102105

103-
for (var i = 0; i < services.Count(); i++)
106+
// Validate counts
107+
ValidateServiceAndInstanceCounts(servicesArray, instancesArray, services.Key);
108+
109+
for (var i = 0; i < servicesArray.Length; i++)
104110
{
105-
clonedCollection.CloneSingleton(services.ElementAt(i), instances.ElementAt(i));
111+
clonedCollection.CloneSingleton(servicesArray[i], instancesArray[i]);
106112
}
107113
}
108114

@@ -112,25 +118,46 @@ public static IServiceCollection CreateChildContainer(this IServiceProvider serv
112118
// We need a service scope to resolve them.
113119
using var scope = serviceProvider.CreateScope();
114120

115-
var instances = scope.ServiceProvider.GetServices(services.Key);
121+
// Materialize services and instances to arrays once.
122+
var servicesArray = services.ToArray();
123+
var instancesArray = scope.ServiceProvider.GetServices(services.Key)?.ToArray() ?? Array.Empty<object>();
124+
125+
ValidateServiceAndInstanceCounts(servicesArray, instancesArray, services.Key);
116126

117127
// Then we only keep singleton instances.
118-
for (var i = 0; i < services.Count(); i++)
128+
for (var i = 0; i < servicesArray.Length; i++)
119129
{
120-
if (services.ElementAt(i).Lifetime == ServiceLifetime.Singleton)
130+
if (servicesArray[i].Lifetime == ServiceLifetime.Singleton)
121131
{
122-
clonedCollection.CloneSingleton(services.ElementAt(i), instances.ElementAt(i));
132+
clonedCollection.CloneSingleton(servicesArray[i], instancesArray[i]);
123133
}
124134
else
125135
{
126-
clonedCollection.Add(services.ElementAt(i));
136+
clonedCollection.Add(servicesArray[i]);
127137
}
128138
}
129139
}
130140
}
131141

132142
return clonedCollection;
133143
}
144+
145+
private static void ValidateServiceAndInstanceCounts<TService, TInstance>(TService[] servicesArray, TInstance[] instancesArray, Type serviceType)
146+
{
147+
if (servicesArray.Length != instancesArray.Length)
148+
{
149+
var message = $"""
150+
Mismatch detected for type {serviceType}:
151+
services.Count = {servicesArray.Length}, instances.Count = {instancesArray.Length}
152+
Services:
153+
{string.Join(",\n\t", servicesArray.Select(s => s.ToString()))}
154+
Instances:
155+
{string.Join(",\n\t", instancesArray.Select(i => i?.GetType()?.ToString() ?? "null"))}
156+
""";
157+
158+
throw new InvalidOperationException(message);
159+
}
160+
}
134161
}
135162

136163
internal static class ServiceCollectionExtensions

0 commit comments

Comments
 (0)