@@ -35,13 +35,39 @@ T Resolve<T>()
35
35
36
36
public sealed class DIScope : IInstanceResolver , IDisposable
37
37
{
38
+ private struct LazyBindDescriptor
39
+ {
40
+ public readonly Type Type ;
41
+ public readonly Type [ ] InterfaceTypes ;
42
+
43
+ public LazyBindDescriptor ( Type type , Type [ ] interfaceTypes )
44
+ {
45
+ Type = type ;
46
+ InterfaceTypes = interfaceTypes ;
47
+ }
48
+ }
49
+
38
50
private static DIScope m_rootScope ;
39
51
52
+ public static DIScope RootScope
53
+ {
54
+ get
55
+ {
56
+ if ( m_rootScope == null )
57
+ {
58
+ m_rootScope = new DIScope ( ) ;
59
+ }
60
+
61
+ return m_rootScope ;
62
+ }
63
+ }
64
+
40
65
private readonly DisposableGroup m_DisposableGroup = new DisposableGroup ( ) ;
41
66
private readonly Dictionary < Type , LazyBindDescriptor > m_LazyBindDescriptors = new Dictionary < Type , LazyBindDescriptor > ( ) ;
42
67
43
68
private readonly DIScope m_Parent ;
44
69
private readonly Dictionary < Type , object > m_TypesToInstances = new Dictionary < Type , object > ( ) ;
70
+ private readonly HashSet < object > m_ObjectsWithInjectedDependencies = new HashSet < object > ( ) ;
45
71
private bool m_Disposed ;
46
72
47
73
private bool m_ScopeConstructionComplete ;
@@ -52,32 +78,30 @@ public DIScope(DIScope parent = null)
52
78
BindInstanceAsSingle < IInstanceResolver , DIScope > ( this ) ;
53
79
}
54
80
55
- public static DIScope RootScope
81
+ ~ DIScope ( )
56
82
{
57
- get
58
- {
59
- if ( m_rootScope == null ) m_rootScope = new DIScope ( ) ;
60
-
61
- return m_rootScope ;
62
- }
83
+ Dispose ( ) ;
63
84
}
64
85
65
86
public void Dispose ( )
66
87
{
67
88
if ( ! m_Disposed )
68
89
{
69
90
m_TypesToInstances . Clear ( ) ;
91
+ m_ObjectsWithInjectedDependencies . Clear ( ) ;
70
92
m_DisposableGroup . Dispose ( ) ;
71
93
m_Disposed = true ;
72
94
}
73
95
}
74
96
75
- public T Resolve < T > ( )
76
- where T : class
97
+ public T Resolve < T > ( ) where T : class
77
98
{
78
99
if ( ! m_ScopeConstructionComplete )
100
+ {
79
101
throw new ScopeNotFinalizedException (
80
102
$ "Trying to Resolve type { typeof ( T ) } , but the DISCope is not yet finalized! You should call FinalizeScopeConstruction before any of the Resolve calls.") ;
103
+ }
104
+
81
105
//if we have this type as lazy-bound instance - we are going to instantiate it now
82
106
if ( m_LazyBindDescriptors . TryGetValue ( typeof ( T ) , out var lazyBindDescriptor ) )
83
107
{
@@ -88,7 +112,10 @@ public T Resolve<T>()
88
112
89
113
if ( ! m_TypesToInstances . TryGetValue ( typeof ( T ) , out var value ) )
90
114
{
91
- if ( m_Parent != null ) return m_Parent . Resolve < T > ( ) ;
115
+ if ( m_Parent != null )
116
+ {
117
+ return m_Parent . Resolve < T > ( ) ;
118
+ }
92
119
93
120
throw new NoInstanceToInjectException ( $ "Injection of type { typeof ( T ) } failed.") ;
94
121
}
@@ -98,6 +125,11 @@ public T Resolve<T>()
98
125
99
126
public void InjectIn ( object obj )
100
127
{
128
+ if ( m_ObjectsWithInjectedDependencies . Contains ( obj ) )
129
+ {
130
+ return ;
131
+ }
132
+
101
133
if ( CachedReflectionUtility . TryGetInjectableMethod ( obj . GetType ( ) , out var injectionMethod ) )
102
134
{
103
135
var parameters = CachedReflectionUtility . GetMethodParameters ( injectionMethod ) ;
@@ -114,19 +146,18 @@ public void InjectIn(object obj)
114
146
}
115
147
116
148
injectionMethod . Invoke ( obj , paramColleciton ) ;
149
+ m_ObjectsWithInjectedDependencies . Add ( obj ) ;
117
150
}
118
151
}
119
152
120
153
public void InjectIn ( GameObject go )
121
154
{
122
- var components = go . GetComponentsInChildren < Component > ( ) ;
123
-
124
- foreach ( var component in components ) InjectIn ( component ) ;
125
- }
155
+ var components = go . GetComponentsInChildren < Component > ( includeInactive : true ) ;
126
156
127
- ~ DIScope ( )
128
- {
129
- Dispose ( ) ;
157
+ foreach ( var component in components )
158
+ {
159
+ InjectIn ( component ) ;
160
+ }
130
161
}
131
162
132
163
public void BindInstanceAsSingle < T > ( T instance ) where T : class
@@ -172,7 +203,10 @@ private void LazyBind(Type type, params Type[] typeAliases)
172
203
{
173
204
var descriptor = new LazyBindDescriptor ( type , typeAliases ) ;
174
205
175
- foreach ( var typeAlias in typeAliases ) m_LazyBindDescriptors [ typeAlias ] = descriptor ;
206
+ foreach ( var typeAlias in typeAliases )
207
+ {
208
+ m_LazyBindDescriptors [ typeAlias ] = descriptor ;
209
+ }
176
210
177
211
m_LazyBindDescriptors [ type ] = descriptor ;
178
212
}
@@ -196,24 +230,34 @@ private object InstantiateLazyBoundObject(LazyBindDescriptor descriptor)
196
230
BindInstanceToType ( instance , descriptor . Type ) ;
197
231
198
232
if ( descriptor . InterfaceTypes != null )
233
+ {
199
234
foreach ( var interfaceType in descriptor . InterfaceTypes )
235
+ {
200
236
BindInstanceToType ( instance , interfaceType ) ;
237
+ }
238
+ }
201
239
202
240
return instance ;
203
241
}
204
242
205
243
private void AddToDisposableGroupIfDisposable ( object instance )
206
244
{
207
- if ( instance is IDisposable disposable ) m_DisposableGroup . Add ( disposable ) ;
245
+ if ( instance is IDisposable disposable )
246
+ {
247
+ m_DisposableGroup . Add ( disposable ) ;
248
+ }
208
249
}
209
250
210
251
/// <summary>
211
- /// This method forces the finalization of construction of DI Scope. It would inject all the instances passed to it directly.
212
- /// Objects that were bound by just type will be instantiated on their first use.
252
+ /// This method forces the finalization of construction of DI Scope. It would inject all the instances passed to it directly.
253
+ /// Objects that were bound by just type will be instantiated on their first use.
213
254
/// </summary>
214
255
public void FinalizeScopeConstruction ( )
215
256
{
216
- if ( m_ScopeConstructionComplete ) return ;
257
+ if ( m_ScopeConstructionComplete )
258
+ {
259
+ return ;
260
+ }
217
261
218
262
m_ScopeConstructionComplete = true ;
219
263
@@ -261,7 +305,10 @@ public static bool TryGetInjectableConstructor(Type type, out ConstructorInfo me
261
305
262
306
private static void CacheTypeMethods ( Type type )
263
307
{
264
- if ( k_ProcessedTypes . Contains ( type ) ) return ;
308
+ if ( k_ProcessedTypes . Contains ( type ) )
309
+ {
310
+ return ;
311
+ }
265
312
266
313
var constructors = type . GetConstructors ( ) ;
267
314
foreach ( var constructorInfo in constructors )
@@ -309,25 +356,17 @@ public static MethodInfo GetTypedResolveMethod(Type parameterType)
309
356
{
310
357
if ( ! k_CachedResolveMethods . TryGetValue ( parameterType , out var resolveMethod ) )
311
358
{
312
- if ( k_ResolveMethod == null ) k_ResolveMethod = typeof ( DIScope ) . GetMethod ( "Resolve" ) ;
359
+ if ( k_ResolveMethod == null )
360
+ {
361
+ k_ResolveMethod = typeof ( DIScope ) . GetMethod ( "Resolve" ) ;
362
+ }
363
+
313
364
resolveMethod = k_ResolveMethod . MakeGenericMethod ( parameterType ) ;
314
365
k_CachedResolveMethods [ parameterType ] = resolveMethod ;
315
366
}
316
367
317
368
return resolveMethod ;
318
369
}
319
370
}
320
-
321
- private struct LazyBindDescriptor
322
- {
323
- public readonly Type Type ;
324
- public readonly Type [ ] InterfaceTypes ;
325
-
326
- public LazyBindDescriptor ( Type type , Type [ ] interfaceTypes )
327
- {
328
- Type = type ;
329
- InterfaceTypes = interfaceTypes ;
330
- }
331
- }
332
371
}
333
372
}
0 commit comments