@@ -119,65 +119,12 @@ public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Fun
119119 limitType ,
120120 ( c , p ) =>
121121 {
122- if ( isAnyKeyQuery )
123- {
124- // AnyKey queries for collections return _all_ explicitly
125- // keyed services. (Services _registered_ with AnyKey are
126- // intentionally excluded, however, since they are
127- // effectively "default" registrations and would be
128- // duplicated in the output if included alongside their
129- // explicitly keyed counterparts.)
130- //
131- // We must resolve each element using the concrete keyed
132- // service so the KeyedServiceParameterInjector can flow
133- // that key into [ServiceKey] parameters.
134- var keyedRegistrations = GetAllSpecificKeyedRegistrations ( c . ComponentRegistry , elementType ) ;
135- var output = factory ( keyedRegistrations . Count ) ;
136- var isFixedSize = output . IsFixedSize ;
137-
138- for ( var i = 0 ; i < keyedRegistrations . Count ; i ++ )
139- {
140- var ( keyedService , itemRegistration ) = keyedRegistrations [ i ] ;
141- var resolveRequest = new ResolveRequest ( keyedService , itemRegistration , p ) ;
142- var component = c . ResolveComponent ( resolveRequest ) ;
143- if ( isFixedSize )
144- {
145- output [ i ] = component ;
146- }
147- else
148- {
149- output . Add ( component ) ;
150- }
151- }
152-
153- return output ;
154- }
155-
156- var itemRegistrations = c . ComponentRegistry
157- . ServiceRegistrationsFor ( elementTypeService )
158- . Where ( cr => ! cr . Registration . Options . HasOption ( RegistrationOptions . ExcludeFromCollections ) )
159- . OrderBy ( cr => cr . Registration . GetRegistrationOrder ( ) )
160- . ToList ( ) ;
161-
162- var defaultOutput = factory ( itemRegistrations . Count ) ;
163- var defaultOutputIsFixedSize = defaultOutput . IsFixedSize ;
164-
165- for ( var i = 0 ; i < itemRegistrations . Count ; i ++ )
166- {
167- var itemRegistration = itemRegistrations [ i ] ;
168- var resolveRequest = new ResolveRequest ( elementTypeService , itemRegistration , p ) ;
169- var component = c . ResolveComponent ( resolveRequest ) ;
170- if ( defaultOutputIsFixedSize )
171- {
172- defaultOutput [ i ] = component ;
173- }
174- else
175- {
176- defaultOutput . Add ( component ) ;
177- }
178- }
122+ var registrationTuples = isAnyKeyQuery
123+ ? GetAllSpecificKeyedRegistrations ( c . ComponentRegistry , elementType )
124+ . ConvertAll ( static tuple => ( ( Service ) tuple . KeyedService , tuple . Registration ) )
125+ : BuildStandardRegistrationList ( c . ComponentRegistry , elementTypeService ) ;
179126
180- return defaultOutput ;
127+ return BuildCollection ( c , factory , registrationTuples , p ) ;
181128 } ) ;
182129
183130 var registration = new ComponentRegistration (
@@ -214,6 +161,24 @@ private static Func<int, IList> GenerateArrayFactory(Type elementType)
214161 return Expression . Lambda < Func < int , IList > > ( newArray , parameter ) . Compile ( ) ;
215162 }
216163
164+ /// <summary>
165+ /// When the query is for "any keyed" enumerable, we need to find all the
166+ /// specific keyed registrations and return them.
167+ /// </summary>
168+ /// <param name="registry">
169+ /// The registry to search for registrations. We need to search the entire
170+ /// registry because "any keyed" could match any specific key.
171+ /// </param>
172+ /// <param name="elementType">
173+ /// The element type of the enumerable being resolved. We need this to
174+ /// filter the registry down to only the relevant registrations.
175+ /// </param>
176+ /// <returns>
177+ /// A list of tuples containing the specific keyed service and the
178+ /// registration for each matching registration. We return the specific
179+ /// keyed service so that we can issue resolve requests that still know the
180+ /// original key.
181+ /// </returns>
217182 private static List < ( KeyedService KeyedService , ServiceRegistration Registration ) > GetAllSpecificKeyedRegistrations ( IComponentRegistry registry , Type elementType )
218183 {
219184 var result = new List < ( KeyedService , ServiceRegistration ) > ( ) ;
@@ -257,4 +222,42 @@ private static Func<int, IList> GenerateArrayFactory(Type elementType)
257222 . OrderBy ( tuple => tuple . Item2 . Registration . GetRegistrationOrder ( ) )
258223 . ToList ( ) ;
259224 }
225+
226+ private static List < ( Service Service , ServiceRegistration Registration ) > BuildStandardRegistrationList ( IComponentRegistry registry , Service elementTypeService )
227+ {
228+ return registry
229+ . ServiceRegistrationsFor ( elementTypeService )
230+ . Where ( cr => ! cr . Registration . Options . HasOption ( RegistrationOptions . ExcludeFromCollections ) )
231+ . OrderBy ( cr => cr . Registration . GetRegistrationOrder ( ) )
232+ . Select ( cr => ( ( Service ) elementTypeService , cr ) )
233+ . ToList ( ) ;
234+ }
235+
236+ private static IList BuildCollection (
237+ IComponentContext context ,
238+ Func < int , IList > factory ,
239+ List < ( Service Service , ServiceRegistration Registration ) > registrations ,
240+ IEnumerable < Parameter > parameters )
241+ {
242+ var output = factory ( registrations . Count ) ;
243+ var isFixedSize = output . IsFixedSize ;
244+
245+ for ( var i = 0 ; i < registrations . Count ; i ++ )
246+ {
247+ var ( service , registration ) = registrations [ i ] ;
248+ var resolveRequest = new ResolveRequest ( service , registration , parameters ) ;
249+ var component = context . ResolveComponent ( resolveRequest ) ;
250+
251+ if ( isFixedSize )
252+ {
253+ output [ i ] = component ;
254+ }
255+ else
256+ {
257+ output . Add ( component ) ;
258+ }
259+ }
260+
261+ return output ;
262+ }
260263}
0 commit comments