@@ -174,24 +174,42 @@ static string GenerateSource(SemanticValues value)
174174
175175 sb . Append ( value . ClassInformation . DeclaredAccessibility ) . Append ( " partial class " ) . Append ( classNameWithGenerics ) . Append ( "\n {\n \n " ) ;
176176
177+ // Prepare helper builder for file-static class members (static flags + default creators)
178+ var fileStaticClassStringBuilder = new StringBuilder ( 256 ) ;
179+ var helperNames = new HashSet < string > ( ) ;
180+ const string fileStaticClassName = "__BindablePropertyInitHelpers" ;
181+
182+ // Build fully-qualified declaring type name for helper method casts (include containing types)
183+ var fullDeclaringType = string . IsNullOrEmpty ( value . ClassInformation . ContainingTypes )
184+ ? classNameWithGenerics
185+ : string . Concat ( value . ClassInformation . ContainingTypes , "." , classNameWithGenerics ) ;
186+
177187 foreach ( var info in value . BindableProperties )
178188 {
179189 if ( info . IsReadOnlyBindableProperty )
180190 {
181- GenerateReadOnlyBindableProperty ( sb , in info ) ;
191+ GenerateReadOnlyBindableProperty ( sb , in info , fileStaticClassName ) ;
182192 }
183193 else
184194 {
185- GenerateBindableProperty ( sb , in info ) ;
195+ GenerateBindableProperty ( sb , in info , fileStaticClassName ) ;
186196 }
187197
188198 if ( info . ShouldUsePropertyInitializer )
189199 {
190- GenerateInitializingProperty ( sb , in info ) ;
191- GenerateDefaultValueMethod ( sb , in info , classNameWithGenerics ) ;
200+ // Generate only references within the class; actual static field and creator method
201+ // will be placed inside the file static helper class below.
202+ if ( helperNames . Add ( info . InitializingPropertyName ) )
203+ {
204+ AppendHelperInitializingField ( fileStaticClassStringBuilder , in info ) ;
205+ }
206+ if ( helperNames . Add ( info . EffectiveDefaultValueCreatorMethodName ) )
207+ {
208+ AppendHelperDefaultValueMethod ( fileStaticClassStringBuilder , in info , fullDeclaringType ) ;
209+ }
192210 }
193211
194- GenerateProperty ( sb , in info ) ;
212+ GenerateProperty ( sb , in info , fileStaticClassName ) ;
195213 }
196214
197215 sb . Append ( '}' ) ;
@@ -206,11 +224,19 @@ static string GenerateSource(SemanticValues value)
206224 }
207225 }
208226
227+ // If we generated any helper members, emit a file static class with them.
228+ if ( fileStaticClassStringBuilder . Length > 0 )
229+ {
230+ sb . Append ( "\n \n file static class " ) . Append ( fileStaticClassName ) . Append ( "\n {\n " ) ;
231+ sb . Append ( fileStaticClassStringBuilder . ToString ( ) ) ;
232+ sb . Append ( "}\n " ) ;
233+ }
234+
209235 return sb . ToString ( ) ;
210236 }
211237
212238 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
213- static void GenerateReadOnlyBindableProperty ( StringBuilder sb , in BindablePropertyModel info )
239+ static void GenerateReadOnlyBindableProperty ( StringBuilder sb , in BindablePropertyModel info , in string fileStaticClassName )
214240 {
215241 // Sanitize the Return Type because Nullable Reference Types cannot be used in the `typeof()` operator
216242 var nonNullableReturnType = ConvertToNonNullableTypeSymbol ( info . ReturnType ) ;
@@ -243,8 +269,15 @@ static void GenerateReadOnlyBindableProperty(StringBuilder sb, in BindableProper
243269 . Append ( info . PropertyChangingMethodName )
244270 . Append ( ", " )
245271 . Append ( info . CoerceValueMethodName )
246- . Append ( ", " )
247- . Append ( info . EffectiveDefaultValueCreatorMethodName )
272+ . Append ( ", " ) ;
273+
274+ if ( info . ShouldUsePropertyInitializer )
275+ {
276+ sb . Append ( fileStaticClassName )
277+ . Append ( '.' ) ;
278+ }
279+
280+ sb . Append ( info . EffectiveDefaultValueCreatorMethodName )
248281 . Append ( ");\n " ) ;
249282
250283 // Generate public BindableProperty from the key
@@ -262,7 +295,7 @@ static void GenerateReadOnlyBindableProperty(StringBuilder sb, in BindableProper
262295 }
263296
264297 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
265- static void GenerateBindableProperty ( StringBuilder sb , in BindablePropertyModel info )
298+ static void GenerateBindableProperty ( StringBuilder sb , in BindablePropertyModel info , in string helperClassName )
266299 {
267300 // Sanitize the Return Type because Nullable Reference Types cannot be used in the `typeof()` operator
268301 var nonNullableReturnType = ConvertToNonNullableTypeSymbol ( info . ReturnType ) ;
@@ -299,15 +332,21 @@ static void GenerateBindableProperty(StringBuilder sb, in BindablePropertyModel
299332 . Append ( info . PropertyChangingMethodName )
300333 . Append ( ", " )
301334 . Append ( info . CoerceValueMethodName )
302- . Append ( ", " )
303- . Append ( info . EffectiveDefaultValueCreatorMethodName )
304- . Append ( ");\n " ) ;
335+ . Append ( ", " ) ;
305336
306- sb . Append ( '\n ' ) ;
337+ if ( info . ShouldUsePropertyInitializer )
338+ {
339+ sb . Append ( helperClassName )
340+ . Append ( '.' ) ;
341+ }
342+
343+ sb . Append ( info . EffectiveDefaultValueCreatorMethodName )
344+ . Append ( ");\n " )
345+ . Append ( '\n ' ) ;
307346 }
308347
309348 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
310- static void GenerateProperty ( StringBuilder sb , in BindablePropertyModel info )
349+ static void GenerateProperty ( StringBuilder sb , in BindablePropertyModel info , in string fileStaticClassName )
311350 {
312351 var sanitizedPropertyName = IsDotnetKeyword ( info . PropertyName ) ? string . Concat ( "@" , info . PropertyName ) : info . PropertyName ;
313352 var formattedReturnType = GetFormattedReturnType ( info . ReturnType ) ;
@@ -324,7 +363,8 @@ static void GenerateProperty(StringBuilder sb, in BindablePropertyModel info)
324363 {
325364 if ( info . ShouldUsePropertyInitializer )
326365 {
327- sb . Append ( info . InitializingPropertyName ) ;
366+ // Now reference the static flag on the file static helper class
367+ sb . Append ( fileStaticClassName ) . Append ( "." ) . Append ( info . InitializingPropertyName ) ;
328368 }
329369 else
330370 {
@@ -556,52 +596,44 @@ static string GetFormattedReturnType(ITypeSymbol typeSymbol)
556596 }
557597
558598 /// <summary>
559- /// Generates the boolean initialization flag used by bindable properties with initializers to indicate that the getter
560- /// should return the backing field while the generated default value method is executing.
599+ /// Appends the initializing flag into the file-static helper class.
561600 /// </summary>
562- /// <param name="sb">The StringBuilder instance to which the initialization field declaration will be appended .</param>
563- /// <param name="info">The model containing metadata about the property for which the initialization field is generated .</param>
564- static void GenerateInitializingProperty ( StringBuilder sb , in BindablePropertyModel info )
601+ /// <param name="helperSb">Helper StringBuilder used to collect helper members .</param>
602+ /// <param name="info">Property model.</param>
603+ static void AppendHelperInitializingField ( StringBuilder helperSb , in BindablePropertyModel info )
565604 {
566- sb . Append ( "bool " )
605+ // Make the flag public static so it can be referenced from the generated partial class in the same file.
606+ helperSb . Append ( "public static bool " )
567607 . Append ( info . InitializingPropertyName )
568608 . Append ( " = false;\n " ) ;
569609 }
570610
571611 /// <summary>
572- /// Generates the default value creator static method used by BindableProperty instances with initializers .
573- /// This method temporarily switches the property's getter to return its backing field while the default value is being computed,
574- /// ensuring that the initializer-provided value is captured and returned as the BindableProperty's default .
612+ /// Appends a default value creator method into the file-static helper class .
613+ /// The method sets the static initializing flag, reads the property's initializer value by casting the bindable
614+ /// to the declaring type, then clears the flag and returns the value .
575615 /// </summary>
576- /// <param name="sb">The StringBuilder instance to which the initialization field declaration will be appended.</param>
577- /// <param name="info">The model containing metadata for the property that requires a default value creator.</param>
578- /// <param name="classNameWithGenerics">The declaring class name including generic type parameters, if any.</param>
579- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
580- static void GenerateDefaultValueMethod ( StringBuilder sb , in BindablePropertyModel info , string classNameWithGenerics )
616+ /// <param name="helperSb">Helper StringBuilder used to collect helper members.</param>
617+ /// <param name="info">Property model.</param>
618+ /// <param name="fullDeclaringType">Declaring type including containing types and generic parameters.</param>
619+ static void AppendHelperDefaultValueMethod ( StringBuilder helperSb , in BindablePropertyModel info , string fullDeclaringType )
581620 {
582621 var sanitizedPropertyName = IsDotnetKeyword ( info . PropertyName ) ? string . Concat ( "@" , info . PropertyName ) : info . PropertyName ;
583622
584- sb . Append ( "static object " )
623+ helperSb . Append ( "public static object " )
585624 . Append ( info . EffectiveDefaultValueCreatorMethodName )
586625 . Append ( "(global::Microsoft.Maui.Controls.BindableObject bindable)\n " )
587626 . Append ( "{\n " )
588- . Append ( "((" )
589- . Append ( classNameWithGenerics )
590- . Append ( ")bindable)." )
591627 . Append ( info . InitializingPropertyName )
592628 . Append ( " = true;\n " )
593- . Append ( "var defaultValue = " )
594- . Append ( "((" )
595- . Append ( classNameWithGenerics )
629+ . Append ( "var defaultValue = ((" )
630+ . Append ( fullDeclaringType )
596631 . Append ( ")bindable)." )
597632 . Append ( sanitizedPropertyName )
598633 . Append ( ";\n " )
599- . Append ( "((" )
600- . Append ( classNameWithGenerics )
601- . Append ( ")bindable)." )
602634 . Append ( info . InitializingPropertyName )
603635 . Append ( " = false;\n " )
604636 . Append ( "return defaultValue;\n " )
605- . Append ( "}\n " ) ;
637+ . Append ( "}\n \n " ) ;
606638 }
607639}
0 commit comments