1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+ using System . Reflection ;
5+
6+ using Microsoft . Extensions . DependencyInjection ;
7+
8+ using Unity . Injection ;
9+ using Unity . Lifetime ;
10+
11+ namespace Unity . DependencyInjection
12+ {
13+ public static class Configuration
14+ {
15+ public static void Register ( IServiceCollection services , IUnityContainer _container )
16+ {
17+ _container . RegisterType < IServiceScopeFactory , ServiceScopeFactory > ( ) ;
18+ _container . RegisterType < IServiceScope , ServiceScope > ( ) ;
19+ _container . RegisterType < IServiceProvider , ServiceProvider > ( ) ;
20+
21+ RegisterEnumerable ( _container ) ;
22+
23+ HashSet < Type > aggregateTypes = GetAggregateTypes ( services ) ;
24+
25+ MethodInfo registerInstance = RegisterInstance ( ) ;
26+
27+ Func < ServiceDescriptor , LifetimeManager > lifetime = GetLifetime ( ) ;
28+
29+ // Configure all registrations into Unity
30+ foreach ( ServiceDescriptor serviceDescriptor in services )
31+ {
32+ RegisterType (
33+ _container ,
34+ lifetime ,
35+ serviceDescriptor ,
36+ aggregateTypes ,
37+ registerInstance ) ;
38+ }
39+ }
40+
41+ private static MethodInfo RegisterInstance ( )
42+ {
43+ return
44+ typeof ( UnityContainerExtensions )
45+ . GetRuntimeMethods ( )
46+ . Single ( o =>
47+ o . IsStatic &&
48+ o . IsPublic &&
49+ o . IsGenericMethod &&
50+ o . Name == "RegisterInstance" &&
51+ o . GetParameters ( ) . Length == 4 ) ;
52+ }
53+
54+ private static HashSet < Type > GetAggregateTypes ( IServiceCollection services )
55+ {
56+ var aggregateTypes = new HashSet < Type >
57+ (
58+ services . GroupBy
59+ (
60+ serviceDescriptor => serviceDescriptor . ServiceType ,
61+ serviceDescriptor => serviceDescriptor
62+ )
63+ . Where ( typeGrouping => typeGrouping . Count ( ) > 1 )
64+ . Select ( type => type . Key )
65+ ) ;
66+
67+ return aggregateTypes ;
68+ }
69+
70+ private static void RegisterEnumerable ( IUnityContainer _container )
71+ {
72+ _container . RegisterType
73+ (
74+ typeof ( IEnumerable < > ) ,
75+ new InjectionFactory
76+ (
77+ ( container , enumerableType , name ) =>
78+ {
79+ Type type = enumerableType . GenericTypeArguments . Single ( ) ;
80+ Type genericType = type . GetGenericTypeDefinition ( ) ;
81+
82+ object [ ] allInstances = container . ResolveAll ( type ) . Concat
83+ (
84+ _container . IsRegistered ( type ) ||
85+ type . GenericTypeArguments . Any ( ) &&
86+ _container . IsRegistered ( genericType )
87+ ? new [ ] { container . Resolve ( type ) }
88+ : new object [ ] { }
89+ )
90+ . ToArray ( ) ;
91+
92+ return
93+ typeof ( Enumerable ) . GetRuntimeMethod ( "OfType" , new [ ] { typeof ( object [ ] ) } )
94+ . MakeGenericMethod ( type )
95+ . Invoke ( null , new object [ ] { allInstances } ) ;
96+ }
97+ )
98+ ) ;
99+ }
100+
101+ private static Func < ServiceDescriptor , LifetimeManager > GetLifetime ( )
102+ {
103+ return serviceDescriptor =>
104+ {
105+ switch ( serviceDescriptor . Lifetime )
106+ {
107+ case ServiceLifetime . Scoped :
108+ return new HierarchicalLifetimeManager ( ) ;
109+
110+ case ServiceLifetime . Singleton :
111+ return new ContainerControlledLifetimeManager ( ) ;
112+
113+ case ServiceLifetime . Transient :
114+ return new TransientLifetimeManager ( ) ;
115+
116+ default :
117+ throw new NotImplementedException ( $ "Unsupported lifetime manager type '{ serviceDescriptor . Lifetime } '") ;
118+ }
119+ } ;
120+ }
121+
122+ private static void RegisterType (
123+ IUnityContainer _container ,
124+ Func < ServiceDescriptor , LifetimeManager > fetchLifetime ,
125+ ServiceDescriptor serviceDescriptor ,
126+ ICollection < Type > aggregateTypes ,
127+ MethodInfo miRegisterInstanceOpen )
128+ {
129+ LifetimeManager lifetimeManager = fetchLifetime ( serviceDescriptor ) ;
130+ bool isAggregateType = aggregateTypes . Contains ( serviceDescriptor . ServiceType ) ;
131+
132+ if ( serviceDescriptor . ImplementationType != null )
133+ {
134+ RegisterImplementation ( _container , serviceDescriptor , isAggregateType , lifetimeManager ) ;
135+ }
136+ else if ( serviceDescriptor . ImplementationFactory != null )
137+ {
138+ RegisterFactory ( _container , serviceDescriptor , isAggregateType , lifetimeManager ) ;
139+ }
140+ else if ( serviceDescriptor . ImplementationInstance != null )
141+ {
142+ RegisterSingleton ( _container , serviceDescriptor , miRegisterInstanceOpen , isAggregateType , lifetimeManager ) ;
143+ }
144+ else
145+ {
146+ throw new InvalidOperationException ( "Unsupported registration type" ) ;
147+ }
148+ }
149+
150+ private static void RegisterImplementation (
151+ IUnityContainer _container ,
152+ ServiceDescriptor serviceDescriptor ,
153+ bool isAggregateType ,
154+ LifetimeManager lifetimeManager )
155+ {
156+ if ( isAggregateType )
157+ {
158+ _container . RegisterType (
159+ serviceDescriptor . ServiceType ,
160+ serviceDescriptor . ImplementationType ,
161+ serviceDescriptor . ImplementationType . AssemblyQualifiedName ,
162+ lifetimeManager ) ;
163+ }
164+ else
165+ {
166+ _container . RegisterType (
167+ serviceDescriptor . ServiceType ,
168+ serviceDescriptor . ImplementationType ,
169+ lifetimeManager ) ;
170+ }
171+ }
172+
173+ private static void RegisterFactory (
174+ IUnityContainer _container ,
175+ ServiceDescriptor serviceDescriptor ,
176+ bool isAggregateType ,
177+ LifetimeManager lifetimeManager )
178+ {
179+ if ( isAggregateType )
180+ {
181+ _container . RegisterType
182+ (
183+ serviceDescriptor . ServiceType ,
184+ serviceDescriptor . ImplementationType . AssemblyQualifiedName ,
185+ lifetimeManager ,
186+ new InjectionFactory
187+ (
188+ container =>
189+ {
190+ var serviceProvider = container . Resolve < IServiceProvider > ( ) ;
191+ object instance = serviceDescriptor . ImplementationFactory ( serviceProvider ) ;
192+ return instance ;
193+ }
194+ )
195+ ) ;
196+ }
197+ else
198+ {
199+ _container . RegisterType
200+ (
201+ serviceDescriptor . ServiceType ,
202+ lifetimeManager ,
203+ new InjectionFactory
204+ (
205+ container =>
206+ {
207+ var serviceProvider = container . Resolve < IServiceProvider > ( ) ;
208+ object instance = serviceDescriptor . ImplementationFactory ( serviceProvider ) ;
209+ return instance ;
210+ }
211+ )
212+ ) ;
213+ }
214+ }
215+
216+ private static void RegisterSingleton (
217+ IUnityContainer _container ,
218+ ServiceDescriptor serviceDescriptor ,
219+ MethodInfo miRegisterInstanceOpen ,
220+ bool isAggregateType ,
221+ LifetimeManager lifetimeManager )
222+ {
223+ if ( isAggregateType )
224+ {
225+ miRegisterInstanceOpen
226+ . MakeGenericMethod ( serviceDescriptor . ServiceType )
227+ . Invoke ( null ,
228+ new [ ]
229+ {
230+ _container , serviceDescriptor . ImplementationType . AssemblyQualifiedName ,
231+ serviceDescriptor . ImplementationInstance , lifetimeManager
232+ } ) ;
233+ }
234+ else
235+ {
236+ _container . RegisterInstance (
237+ serviceDescriptor . ServiceType ,
238+ serviceDescriptor . ImplementationInstance ,
239+ lifetimeManager ) ;
240+ }
241+ }
242+ }
243+ }
0 commit comments