@@ -70,6 +70,62 @@ internal class InternalService : IInternalService
70
70
public string Get ( ) => "InternalService" ;
71
71
}
72
72
73
+ public interface IBaseArgument { }
74
+
75
+ public abstract class AnotherArgument
76
+ {
77
+ public string Value { get ; set ; }
78
+ }
79
+
80
+ public class Argument1A : IBaseArgument { }
81
+
82
+ public class Argument1B : IBaseArgument { }
83
+
84
+ public class Argument1C : IBaseArgument { }
85
+
86
+ public struct Argument2 { }
87
+
88
+ public class Argument3 : AnotherArgument , IBaseArgument { }
89
+
90
+ public interface IGenericService < T , in TIn , out TOut >
91
+ where T : class , IBaseArgument , new ( )
92
+ where TIn : struct
93
+ where TOut : AnotherArgument , IBaseArgument
94
+ {
95
+ TOut Get < TArg > ( T arg1 , TIn arg2 , TArg arg3 ) where TArg : struct ;
96
+ }
97
+
98
+ private class GenericService < T , TIn , TOut > : IGenericService < T , TIn , TOut >
99
+ where T : class , IBaseArgument , new ( )
100
+ where TIn : struct
101
+ where TOut : AnotherArgument , IBaseArgument , new ( )
102
+ {
103
+ protected virtual string Get ( ) => "" ;
104
+
105
+ public TOut Get < TArg > ( T arg1 , TIn arg2 , TArg arg3 ) where TArg : struct
106
+ {
107
+ return new TOut
108
+ {
109
+ Value = $ "{ arg1 . GetType ( ) . Name } _{ arg2 . GetType ( ) . Name } _{ arg3 . GetType ( ) . Name } { Get ( ) } "
110
+ } ;
111
+ }
112
+ }
113
+
114
+ private class DerivedGenericService < T , TIn , TOut > : GenericService < T , TIn , TOut >
115
+ where T : class , IBaseArgument , new ( )
116
+ where TIn : struct
117
+ where TOut : AnotherArgument , IBaseArgument , new ( )
118
+ {
119
+ private readonly string _value ;
120
+
121
+ protected override string Get ( ) => $ "_{ _value } ";
122
+
123
+ public DerivedGenericService ( string value )
124
+ {
125
+ _value = value ;
126
+ }
127
+ }
128
+
73
129
[ Fact ]
74
130
public void ServiceCtorMustBeExecutedAfterMethodIsCalledAndOnlyOnce ( )
75
131
{
@@ -305,5 +361,131 @@ public void InternalsVisibleToAttributeMustAllowToResolveInternalServices()
305
361
306
362
Assert . Equal ( "InternalService" , result ) ;
307
363
}
364
+
365
+ [ Fact ]
366
+ public void ClosedGenericServiceMustBeResolved ( )
367
+ {
368
+ var result = new UnityContainer ( )
369
+ . RegisterLazy (
370
+ typeof ( IGenericService < Argument1A , Argument2 , Argument3 > ) ,
371
+ typeof ( GenericService < Argument1A , Argument2 , Argument3 > ) )
372
+ . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( )
373
+ . Get ( new Argument1A ( ) , new Argument2 ( ) , 42 ) ;
374
+
375
+ Assert . Equal ( "Argument1A_Argument2_Int32" , result . Value ) ;
376
+ }
377
+
378
+ [ Fact ]
379
+ public void OpenedGenericServiceMustBeResolved ( )
380
+ {
381
+ var result = new UnityContainer ( )
382
+ . RegisterLazy ( typeof ( IGenericService < , , > ) , typeof ( GenericService < , , > ) )
383
+ . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( )
384
+ . Get ( new Argument1A ( ) , new Argument2 ( ) , 42 ) ;
385
+
386
+ Assert . Equal ( "Argument1A_Argument2_Int32" , result . Value ) ;
387
+ }
388
+
389
+ [ Fact ]
390
+ public void GenericServiceMustBeResolvedWithCorrectLifetime ( )
391
+ {
392
+ var container = new UnityContainer ( )
393
+ . RegisterLazy (
394
+ typeof ( IGenericService < , , > ) ,
395
+ typeof ( GenericService < , , > ) ,
396
+ ( ) => new TransientLifetimeManager ( ) )
397
+ . RegisterLazy (
398
+ typeof ( IGenericService < Argument1A , Argument2 , Argument3 > ) ,
399
+ typeof ( GenericService < Argument1A , Argument2 , Argument3 > ) ,
400
+ ( ) => new ContainerControlledLifetimeManager ( ) )
401
+ . RegisterLazy (
402
+ typeof ( IGenericService < Argument1B , Argument2 , Argument3 > ) ,
403
+ typeof ( GenericService < Argument1B , Argument2 , Argument3 > ) ,
404
+ ( ) => new HierarchicalLifetimeManager ( ) )
405
+ . RegisterLazy (
406
+ typeof ( IGenericService < Argument1C , Argument2 , Argument3 > ) ,
407
+ typeof ( GenericService < Argument1C , Argument2 , Argument3 > ) ,
408
+ ( ) => new TransientLifetimeManager ( ) ) ;
409
+
410
+ var service1 = container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( ) ;
411
+ var service2 = container . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( ) ;
412
+ var service3 = container . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( ) ;
413
+
414
+ Assert . Same ( service1 , container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( ) ) ;
415
+ Assert . Same ( service2 , container . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( ) ) ;
416
+ Assert . NotSame ( service3 , container . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( ) ) ;
417
+
418
+ using ( var childContainer = container . CreateChildContainer ( ) )
419
+ {
420
+ Assert . Same ( service1 , childContainer . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( ) ) ;
421
+ Assert . NotSame ( service2 , childContainer . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( ) ) ;
422
+ Assert . NotSame ( service3 , childContainer . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( ) ) ;
423
+ }
424
+ }
425
+
426
+ [ Fact ]
427
+ public void GenericServicesMustBeResolvedByNameWithCorrectLifetime ( )
428
+ {
429
+ const string singleton = "singleton" ;
430
+ const string hierarchical = "hierarchical" ;
431
+ const string transient = "transient" ;
432
+
433
+ var container = new UnityContainer ( )
434
+ . RegisterLazy (
435
+ typeof ( IGenericService < , , > ) ,
436
+ typeof ( GenericService < , , > ) ,
437
+ singleton ,
438
+ ( ) => new ContainerControlledLifetimeManager ( ) )
439
+ . RegisterLazy (
440
+ typeof ( IGenericService < , , > ) ,
441
+ typeof ( GenericService < , , > ) ,
442
+ hierarchical ,
443
+ ( ) => new HierarchicalLifetimeManager ( ) )
444
+ . RegisterLazy (
445
+ typeof ( IGenericService < , , > ) ,
446
+ typeof ( GenericService < , , > ) ,
447
+ transient ,
448
+ ( ) => new TransientLifetimeManager ( ) ) ;
449
+
450
+ var service1 = container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( singleton ) ;
451
+ var service2 = container . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( hierarchical ) ;
452
+ var service3 = container . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( transient ) ;
453
+
454
+ Assert . Same ( service1 , container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( singleton ) ) ;
455
+ Assert . Same ( service2 , container . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( hierarchical ) ) ;
456
+ Assert . NotSame ( service3 , container . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( transient ) ) ;
457
+
458
+ using ( var childContainer = container . CreateChildContainer ( ) )
459
+ {
460
+ Assert . Same ( service1 , childContainer . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( singleton ) ) ;
461
+ Assert . NotSame ( service2 , childContainer . Resolve < IGenericService < Argument1B , Argument2 , Argument3 > > ( hierarchical ) ) ;
462
+ Assert . NotSame ( service3 , childContainer . Resolve < IGenericService < Argument1C , Argument2 , Argument3 > > ( transient ) ) ;
463
+ }
464
+ }
465
+
466
+ [ Fact ]
467
+ public void GenericServicesMustBeResolvedByNameWithCorrectInjectionMembers ( )
468
+ {
469
+ const string value1 = "value1" ;
470
+ const string value2 = "value2" ;
471
+
472
+ var container = new UnityContainer ( )
473
+ . RegisterLazy (
474
+ typeof ( IGenericService < , , > ) ,
475
+ typeof ( DerivedGenericService < , , > ) ,
476
+ value1 ,
477
+ new InjectionConstructor ( value1 ) )
478
+ . RegisterLazy (
479
+ typeof ( IGenericService < , , > ) ,
480
+ typeof ( DerivedGenericService < , , > ) ,
481
+ value2 ,
482
+ new InjectionConstructor ( value2 ) ) ;
483
+
484
+ var service1 = container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( value1 ) ;
485
+ var service2 = container . Resolve < IGenericService < Argument1A , Argument2 , Argument3 > > ( value2 ) ;
486
+
487
+ Assert . Equal ( $ "Argument1A_Argument2_Int32_{ value1 } ", service1 . Get ( new Argument1A ( ) , new Argument2 ( ) , 42 ) . Value ) ;
488
+ Assert . Equal ( $ "Argument1A_Argument2_Int32_{ value2 } ", service2 . Get ( new Argument1A ( ) , new Argument2 ( ) , 42 ) . Value ) ;
489
+ }
308
490
}
309
491
}
0 commit comments