@@ -75,6 +75,9 @@ public partial class UnityContainer
75
75
internal SetPolicyDelegate SetPolicy ;
76
76
internal ClearPolicyDelegate ClearPolicy ;
77
77
78
+ private Func < Type , string , IPolicySet > _get ;
79
+ private Func < Type , string , Type , IPolicySet > _getGenericRegistration ;
80
+
78
81
#endregion
79
82
80
83
@@ -107,15 +110,19 @@ public UnityContainer()
107
110
SetPolicy = Set ;
108
111
ClearPolicy = Clear ;
109
112
113
+ _get = Get ;
114
+ _getGenericRegistration = GetOrAddGeneric ;
115
+
116
+
110
117
// TODO: Initialize disposables
111
118
_lifetimeContainer . Add ( _strategies ) ;
112
119
_lifetimeContainer . Add ( _buildPlanStrategies ) ;
113
120
114
121
// Main strategy chain
115
- _strategies . Add ( new ArrayResolveStrategy ( typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveArray ) ) ,
116
- typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveLazyArray ) ) ) , UnityBuildStage . Enumerable ) ;
117
- _strategies . Add ( new EnumerableResolveStrategy ( typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveEnumerable ) ) ,
118
- typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveLazyEnumerable ) ) ) , UnityBuildStage . Enumerable ) ;
122
+ _strategies . Add ( new ArrayResolveStrategy ( typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveArray ) ) ,
123
+ typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveGenericArray ) ) ) , UnityBuildStage . Enumerable ) ;
124
+ _strategies . Add ( new EnumerableResolveStrategy ( typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveEnumerable ) ) ,
125
+ typeof ( UnityContainer ) . GetTypeInfo ( ) . GetDeclaredMethod ( nameof ( ResolveGenericEnumerable ) ) ) , UnityBuildStage . Enumerable ) ;
119
126
_strategies . Add ( new BuildKeyMappingStrategy ( ) , UnityBuildStage . TypeMapping ) ;
120
127
_strategies . Add ( new LifetimeStrategy ( ) , UnityBuildStage . Lifetime ) ;
121
128
_strategies . Add ( new BuildPlanStrategy ( ) , UnityBuildStage . Creation ) ;
@@ -131,7 +138,7 @@ public UnityContainer()
131
138
_strategies . Invalidated += OnStrategiesChanged ;
132
139
133
140
// Default Policies
134
- Set ( null , null , GetDefaultPolicies ( ) ) ;
141
+ Set ( null , null , GetDefaultPolicies ( ) ) ;
135
142
Set ( typeof ( Func < > ) , string . Empty , typeof ( ILifetimePolicy ) , new PerResolveLifetimeManager ( ) ) ;
136
143
Set ( typeof ( Func < > ) , string . Empty , typeof ( IBuildPlanPolicy ) , new DeferredResolveCreatorPolicy ( ) ) ;
137
144
Set ( typeof ( Lazy < > ) , string . Empty , typeof ( IBuildPlanCreatorPolicy ) , new GenericLazyBuildPlanCreatorPolicy ( ) ) ;
@@ -167,6 +174,9 @@ private UnityContainer(UnityContainer parent)
167
174
SetPolicy = CreateAndSetPolicy ;
168
175
ClearPolicy = delegate { } ;
169
176
177
+ _get = _parent . _get ;
178
+ _getGenericRegistration = _parent . _getGenericRegistration ;
179
+
170
180
// Strategies
171
181
_strategies = _parent . _strategies ;
172
182
_buildPlanStrategies = _parent . _buildPlanStrategies ;
@@ -225,11 +235,27 @@ private void SetupChildContainerBehaviors()
225
235
{
226
236
_registrations = new HashRegistry < Type , IRegistry < string , IPolicySet > > ( ContainerInitialCapacity ) ;
227
237
IsTypeRegistered = IsTypeRegisteredLocally ;
228
- GetRegistration = ( type , name ) => Get ( type , name ) ?? _parent . GetRegistration ( type , name ) ;
229
238
Register = AddOrUpdate ;
230
239
GetPolicy = Get ;
231
240
SetPolicy = Set ;
232
241
ClearPolicy = Clear ;
242
+
243
+ GetRegistration = GetDynamicRegistration ;
244
+
245
+ _get = GetChained ;
246
+ _getGenericRegistration = GetOrAddGeneric ;
247
+ }
248
+
249
+
250
+ private IPolicySet GetDynamicRegistration ( Type type , string name )
251
+ {
252
+ var registration = _get ( type , name ) ;
253
+ if ( null != registration ) return registration ;
254
+
255
+ var info = type . GetTypeInfo ( ) ;
256
+ return ! info . IsGenericType
257
+ ? _root . GetOrAdd ( type , name )
258
+ : GetOrAddGeneric ( type , name , info . GetGenericTypeDefinition ( ) ) ;
233
259
}
234
260
235
261
private static object ThrowingBuildUp ( IBuilderContext context )
@@ -362,19 +388,36 @@ private static MiniHashSet<InternalRegistration> GetNamedRegistrations(UnityCont
362
388
return set ;
363
389
}
364
390
365
- private static MiniHashSet < InternalRegistration > GetNotEmptyRegistrations ( UnityContainer container , Type type )
391
+ private static void GetNamedRegistrations ( UnityContainer container , Type type , MiniHashSet < InternalRegistration > set )
366
392
{
367
- MiniHashSet < InternalRegistration > set ;
368
-
369
393
if ( null != container . _parent )
370
- set = GetNotEmptyRegistrations ( container . _parent , type ) ;
371
- else
372
- set = new MiniHashSet < InternalRegistration > ( ) ;
394
+ GetNamedRegistrations ( container . _parent , type , set ) ;
395
+
396
+ if ( null == container . _registrations ) return ;
397
+
398
+ var registrations = container . Get ( type ) ;
399
+ if ( registrations ? . Values != null )
400
+ {
401
+ var registry = registrations . Values ;
402
+ foreach ( var entry in registry )
403
+ {
404
+ if ( entry is IContainerRegistration registration &&
405
+ ! string . IsNullOrEmpty ( registration . Name ) )
406
+ set . Add ( ( InternalRegistration ) registration ) ;
407
+ }
408
+ }
409
+ }
410
+
411
+ private static MiniHashSet < InternalRegistration > GetExplicitRegistrations ( UnityContainer container , Type type )
412
+ {
413
+ var set = null != container . _parent
414
+ ? GetExplicitRegistrations ( container . _parent , type )
415
+ : new MiniHashSet < InternalRegistration > ( ) ;
373
416
374
417
if ( null == container . _registrations ) return set ;
375
418
376
419
var registrations = container . Get ( type ) ;
377
- if ( null != registrations && null != registrations . Values )
420
+ if ( registrations ? . Values != null )
378
421
{
379
422
var registry = registrations . Values ;
380
423
foreach ( var entry in registry )
@@ -389,7 +432,7 @@ private static MiniHashSet<InternalRegistration> GetNotEmptyRegistrations(UnityC
389
432
if ( generic != type )
390
433
{
391
434
registrations = container . Get ( generic ) ;
392
- if ( null != registrations && null != registrations . Values )
435
+ if ( registrations ? . Values != null )
393
436
{
394
437
var registry = registrations . Values ;
395
438
foreach ( var entry in registry )
@@ -402,8 +445,29 @@ private static MiniHashSet<InternalRegistration> GetNotEmptyRegistrations(UnityC
402
445
403
446
return set ;
404
447
}
405
-
406
- internal IList < BuilderStrategy > GetBuilders ( InternalRegistration registration )
448
+
449
+ private static void GetExplicitRegistrations ( UnityContainer container , Type type , MiniHashSet < InternalRegistration > set )
450
+ {
451
+ if ( null != container . _parent )
452
+ GetExplicitRegistrations ( container . _parent , type , set ) ;
453
+
454
+ if ( null == container . _registrations ) return ;
455
+
456
+ var registrations = container . Get ( type ) ;
457
+ if ( registrations ? . Values != null )
458
+ {
459
+ var registry = registrations . Values ;
460
+ foreach ( var entry in registry )
461
+ {
462
+ if ( entry is IContainerRegistration registration && string . Empty != registration . Name )
463
+ set . Add ( ( InternalRegistration ) registration ) ;
464
+ }
465
+ }
466
+
467
+ return ;
468
+ }
469
+
470
+ private IList < BuilderStrategy > GetBuilders ( InternalRegistration registration )
407
471
{
408
472
var chain = new List < BuilderStrategy > ( ) ;
409
473
var strategies = _buildChain ;
@@ -433,6 +497,38 @@ private IPolicySet CreateRegistration(Type type, string name, Type policyInterfa
433
497
return registration ;
434
498
}
435
499
500
+ internal Type GetFinalType ( Type argType )
501
+ {
502
+ Type next ;
503
+ for ( var type = argType ; null != type ; type = next )
504
+ {
505
+ var info = type . GetTypeInfo ( ) ;
506
+ if ( info . IsGenericType )
507
+ {
508
+ var definition = info . GetGenericTypeDefinition ( ) ;
509
+ if ( typeof ( Lazy < > ) != definition &&
510
+ typeof ( Func < > ) != definition &&
511
+ null != GetChained ( definition ) ) return definition ;
512
+
513
+ next = info . GenericTypeArguments [ 0 ] ;
514
+ if ( null != GetChained ( next ) ) return next ;
515
+ }
516
+ else if ( info . IsArray )
517
+ {
518
+ next = info . GetElementType ( ) ;
519
+ if ( typeof ( Lazy < > ) != next &&
520
+ typeof ( Func < > ) != next &&
521
+ null != GetChained ( next ) ) return next ;
522
+ }
523
+ else
524
+ {
525
+ return type ;
526
+ }
527
+ }
528
+
529
+ return argType ;
530
+ }
531
+
436
532
#endregion
437
533
438
534
0 commit comments