@@ -23,6 +23,14 @@ public CompositionCode Build(CompositionCode composition)
2323 var hasDisposable = composition . DisposablesCount > 0 ;
2424 var hasAsyncDisposable = composition . AsyncDisposableCount > 0 ;
2525 var hints = composition . Source . Source . Hints ;
26+ var hasStateObjectScope = hints . ScopeStrategy == ScopeStrategy . StateObject ;
27+ var hasScopedLifetimes = composition . Singletons . Any ( i => i . Node . ActualLifetime == Lifetime . Scoped ) ;
28+ var rootDisposablesCount = hasStateObjectScope
29+ ? composition . TotalDisposablesCount - composition . DisposablesScopedCount
30+ : composition . TotalDisposablesCount ;
31+ var singletonFieldsToReset = hasStateObjectScope
32+ ? composition . Singletons . Where ( i => i . Node . ActualLifetime == Lifetime . Singleton ) . ToImmutableArray ( )
33+ : composition . Singletons ;
2634 var isCommentsEnabled = hints . IsCommentsEnabled ;
2735 if ( isCommentsEnabled )
2836 {
@@ -34,27 +42,30 @@ public CompositionCode Build(CompositionCode composition)
3442 code . AppendLine ( $ "{ composition . Source . Source . Hints . DisposeMethodModifiers } void Dispose()") ;
3543 using ( code . CreateBlock ( ) )
3644 {
37- AddSyncPart ( composition , code , false ) ;
38- code . AppendLine ( ) ;
39- code . AppendLine ( "while (disposeIndex-- > 0)" ) ;
40- using ( code . CreateBlock ( ) )
45+ AddSyncPart ( composition , code , false , rootDisposablesCount , hasStateObjectScope , hasScopedLifetimes , singletonFieldsToReset ) ;
46+ if ( rootDisposablesCount > 0 )
4147 {
42- code . AppendLine ( "switch (disposables[disposeIndex])" ) ;
48+ code . AppendLine ( ) ;
49+ code . AppendLine ( "while (disposeIndex-- > 0)" ) ;
4350 using ( code . CreateBlock ( ) )
4451 {
45- if ( hasDisposable )
46- {
47- AddDisposePart ( code ) ;
48- }
49-
50- if ( hasAsyncDisposable )
52+ code . AppendLine ( "switch (disposables[disposeIndex])" ) ;
53+ using ( code . CreateBlock ( ) )
5154 {
5255 if ( hasDisposable )
5356 {
54- code . AppendLine ( ) ;
57+ AddDisposePart ( code ) ;
5558 }
5659
57- AddDisposeAsyncPart ( code , false ) ;
60+ if ( hasAsyncDisposable )
61+ {
62+ if ( hasDisposable )
63+ {
64+ code . AppendLine ( ) ;
65+ }
66+
67+ AddDisposeAsyncPart ( code , false ) ;
68+ }
5869 }
5970 }
6071 }
@@ -86,27 +97,30 @@ public CompositionCode Build(CompositionCode composition)
8697 code . AppendLine ( $ "{ composition . Source . Source . Hints . DisposeAsyncMethodModifiers } async { Names . ValueTaskTypeName } DisposeAsync()") ;
8798 using ( code . CreateBlock ( ) )
8899 {
89- AddSyncPart ( composition , code , true ) ;
90- code . AppendLine ( ) ;
91- code . AppendLine ( "while (disposeIndex-- > 0)" ) ;
92- using ( code . CreateBlock ( ) )
100+ AddSyncPart ( composition , code , true , rootDisposablesCount , hasStateObjectScope , hasScopedLifetimes , singletonFieldsToReset ) ;
101+ if ( rootDisposablesCount > 0 )
93102 {
94- code . AppendLine ( "switch (disposables[disposeIndex])" ) ;
103+ code . AppendLine ( ) ;
104+ code . AppendLine ( "while (disposeIndex-- > 0)" ) ;
95105 using ( code . CreateBlock ( ) )
96106 {
97- if ( hasAsyncDisposable )
98- {
99- AddDisposeAsyncPart ( code , true ) ;
100- }
101-
102- if ( hasDisposable )
107+ code . AppendLine ( "switch (disposables[disposeIndex])" ) ;
108+ using ( code . CreateBlock ( ) )
103109 {
104110 if ( hasAsyncDisposable )
105111 {
106- code . AppendLine ( ) ;
112+ AddDisposeAsyncPart ( code , true ) ;
107113 }
108114
109- AddDisposePart ( code ) ;
115+ if ( hasDisposable )
116+ {
117+ if ( hasAsyncDisposable )
118+ {
119+ code . AppendLine ( ) ;
120+ }
121+
122+ AddDisposePart ( code ) ;
123+ }
110124 }
111125 }
112126 }
@@ -182,10 +196,26 @@ private static void AddDisposePart(Lines code)
182196 }
183197 }
184198
185- private void AddSyncPart ( CompositionCode composition , Lines code , bool isAsync )
199+ private void AddSyncPart (
200+ CompositionCode composition ,
201+ Lines code ,
202+ bool isAsync ,
203+ int rootDisposablesCount ,
204+ bool hasStateObjectScope ,
205+ bool hasScopedLifetimes ,
206+ ImmutableArray < VarDeclaration > singletonFieldsToReset )
186207 {
187- code . AppendLine ( "int disposeIndex;" ) ;
188- code . AppendLine ( "object[] disposables;" ) ;
208+ if ( hasStateObjectScope && hasScopedLifetimes )
209+ {
210+ code . AppendLine ( $ "{ Names . RootScopeFieldName } .Dispose();") ;
211+ }
212+
213+ if ( rootDisposablesCount > 0 )
214+ {
215+ code . AppendLine ( "int disposeIndex;" ) ;
216+ code . AppendLine ( "object[] disposables;" ) ;
217+ }
218+
189219 var isLockRequired = composition . IsLockRequired ( locks ) ;
190220 if ( isLockRequired )
191221 {
@@ -194,11 +224,15 @@ private void AddSyncPart(CompositionCode composition, Lines code, bool isAsync)
194224 code . IncIndent ( ) ;
195225 }
196226
197- code . AppendLine ( $ "disposeIndex = { Names . DisposeIndexFieldName } ;") ;
198- code . AppendLine ( $ "{ Names . DisposeIndexFieldName } = 0;") ;
199- code . AppendLine ( $ "disposables = { Names . DisposablesFieldName } ;") ;
200- code . AppendLine ( $ "{ Names . DisposablesFieldName } = new object[{ composition . TotalDisposablesCount . ToString ( ) } ];") ;
201- foreach ( var singletonField in composition . Singletons )
227+ if ( rootDisposablesCount > 0 )
228+ {
229+ code . AppendLine ( $ "disposeIndex = { Names . DisposeIndexFieldName } ;") ;
230+ code . AppendLine ( $ "{ Names . DisposeIndexFieldName } = 0;") ;
231+ code . AppendLine ( $ "disposables = { Names . DisposablesFieldName } ;") ;
232+ code . AppendLine ( $ "{ Names . DisposablesFieldName } = new object[{ rootDisposablesCount . ToString ( ) } ];") ;
233+ }
234+
235+ foreach ( var singletonField in singletonFieldsToReset )
202236 {
203237 if ( singletonField . InstanceType . IsValueType )
204238 {
@@ -218,4 +252,4 @@ private void AddSyncPart(CompositionCode composition, Lines code, bool isAsync)
218252 code . AppendLine ( BlockFinish ) ;
219253 }
220254 }
221- }
255+ }
0 commit comments