1+ using System ;
2+ using System . Threading ;
3+ using Microsoft . Extensions . DependencyInjection ;
4+
5+ namespace Eocron . DependencyInjection
6+ {
7+ public static partial class ServiceCollectionServiceExtensions
8+ {
9+ public static IServiceCollection Add ( this IServiceCollection services , ServiceDescriptor descriptor , DecoratorChain chain )
10+ {
11+ ArgumentNullException . ThrowIfNull ( descriptor ) ;
12+ ArgumentNullException . ThrowIfNull ( chain ) ;
13+
14+ if ( chain . Items . Count == 0 )
15+ {
16+ services . Add ( descriptor ) ;
17+ return services ;
18+ }
19+
20+ var implementationDescriptor = CloneWithNewKey ( descriptor ) ;
21+ services . Add ( implementationDescriptor ) ;
22+ var prevKey = implementationDescriptor . ServiceKey ;
23+ for ( var i = chain . Items . Count - 1 ; i >= 0 ; i -- )
24+ {
25+ var d = chain . Items [ i ] ;
26+ var isLast = i == 0 ;
27+ var pk = prevKey ;
28+ if ( isLast )
29+ {
30+ if ( descriptor . IsKeyedService )
31+ {
32+ services . Add ( new ServiceDescriptor (
33+ descriptor . ServiceType ,
34+ descriptor . ServiceKey ,
35+ ( sp , _ ) => d ( sp , sp . GetRequiredKeyedService ( descriptor . ServiceType , pk ) ) ,
36+ descriptor . Lifetime ) ) ;
37+ }
38+ else
39+ {
40+ services . Add ( new ServiceDescriptor (
41+ descriptor . ServiceType ,
42+ sp => d ( sp , sp . GetRequiredKeyedService ( descriptor . ServiceType , pk ) ) ,
43+ descriptor . Lifetime ) ) ;
44+ }
45+ }
46+ else
47+ {
48+ var nextKey = GenerateKey ( ) ;
49+ services . Add ( new ServiceDescriptor (
50+ descriptor . ServiceType ,
51+ nextKey ,
52+ ( sp , _ ) => d ( sp , sp . GetRequiredKeyedService ( descriptor . ServiceType , pk ) ) ,
53+ descriptor . Lifetime ) ) ;
54+ prevKey = nextKey ;
55+ }
56+ }
57+
58+ return services ;
59+ }
60+
61+ private static string GenerateKey ( )
62+ {
63+ return Interlocked . Increment ( ref _counter ) . ToString ( "000000" ) + "_decorator" ;
64+ }
65+
66+ private static long _counter = 0 ;
67+
68+ private static ServiceDescriptor CloneWithNewKey ( ServiceDescriptor descriptor )
69+ {
70+ var newKey = GenerateKey ( ) ;
71+ if ( descriptor . IsKeyedService )
72+ {
73+ if ( descriptor . KeyedImplementationInstance != null )
74+ {
75+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , ( _ , _ ) => descriptor . KeyedImplementationInstance , descriptor . Lifetime ) ;
76+ }
77+ if ( descriptor . KeyedImplementationFactory != null )
78+ {
79+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , ( sp , _ ) => descriptor . KeyedImplementationFactory ( sp , descriptor . ServiceKey ) , descriptor . Lifetime ) ;
80+ }
81+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , descriptor . KeyedImplementationType , descriptor . Lifetime ) ;
82+ }
83+
84+ if ( descriptor . ImplementationInstance != null )
85+ {
86+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , ( _ , _ ) => descriptor . ImplementationInstance , descriptor . Lifetime ) ;
87+ }
88+ if ( descriptor . ImplementationFactory != null )
89+ {
90+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , ( sp , _ ) => descriptor . ImplementationFactory ( sp ) , descriptor . Lifetime ) ;
91+ }
92+ return new ServiceDescriptor ( descriptor . ServiceType , newKey , descriptor . ImplementationType , descriptor . Lifetime ) ;
93+ }
94+ }
95+ }
0 commit comments