@@ -16,6 +16,7 @@ public class BoundFieldAsProperty : PropertyWriter
1616 {
1717 readonly Field field ;
1818 readonly CodeGenerationOptions opt ;
19+ readonly FieldWriter ? cached_field ;
1920
2021 public BoundFieldAsProperty ( GenBase type , Field field , CodeGenerationOptions opt )
2122 {
@@ -59,10 +60,23 @@ public BoundFieldAsProperty (GenBase type, Field field, CodeGenerationOptions op
5960
6061 if ( ! field . IsConst )
6162 HasSet = true ;
63+
64+ // This is considerably harder to support if we don't have NRT, due to the
65+ // differences in handling nullable value and reference types.
66+ if ( field . IsConst && opt . SupportNullableReferenceTypes )
67+ cached_field = new FieldWriter {
68+ Name = field . CachedMemberName ,
69+ Type = new TypeReferenceWriter ( fieldType . TrimEnd ( '?' ) ) { Nullable = true } ,
70+ IsStatic = true ,
71+ IsPrivate = true ,
72+ UseExplicitPrivateKeyword = type is InterfaceGen ,
73+ } ;
6274 }
6375
6476 public override void Write ( CodeWriter writer )
6577 {
78+ cached_field ? . Write ( writer ) ;
79+
6680 // This is just a temporary hack to write the [GeneratedEnum] attribute before the // Metadata.xml
6781 // comment so that we are 100% equal to pre-refactor.
6882 var generated_attr = Attributes . OfType < GeneratedEnumAttr > ( ) . FirstOrDefault ( ) ;
@@ -82,6 +96,13 @@ public override void WriteAttributes (CodeWriter writer)
8296
8397 protected override void WriteGetterBody ( CodeWriter writer )
8498 {
99+ var cached_field_type = cached_field is not null ? new TypeReferenceWriter ( cached_field . Type . Namespace , cached_field . Type . Name ) : null ;
100+
101+ if ( cached_field is not null ) {
102+ writer . WriteLine ( $ "if ({ field . CachedMemberName } != null) return ({ cached_field_type } ){ field . CachedMemberName } ;") ;
103+ writer . WriteLine ( ) ;
104+ }
105+
85106 writer . WriteLine ( $ "const string __id = \" { field . JavaName } .{ field . Symbol . JniName } \" ;") ;
86107 writer . WriteLine ( ) ;
87108
@@ -93,24 +114,27 @@ protected override void WriteGetterBody (CodeWriter writer)
93114
94115 writer . WriteLine ( $ "var __v = { field . Symbol . ReturnCast } _members.{ indirect } .{ invoke } (__id{ ( field . IsStatic ? "" : ", this" ) } );") ;
95116
117+ var cache_setter = cached_field is not null ? $ "({ PropertyType } )({ field . CachedMemberName } = " : "" ;
118+ var cache_setter_end = cached_field is not null ? ")" : "" ;
119+
96120 if ( opt . CodeGenerationTarget == CodeGenerationTarget . JavaInterop1 ) {
97121 if ( field . Symbol . NativeType == field . Symbol . FullName ) {
98- writer . WriteLine ( "return __v;" ) ;
122+ writer . WriteLine ( $ "return { cache_setter } __v{ cache_setter_end } ;") ;
99123 return ;
100124 }
101- writer . Write ( "return global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<" ) ;
125+ writer . Write ( $ "return { cache_setter } global::Java.Interop.JniEnvironment.Runtime.ValueManager.GetValue<") ;
102126 PropertyType . WriteTypeReference ( writer ) ;
103127 writer . Write ( ">(ref __v, JniObjectReferenceOptions.Copy)" ) ;
104- writer . WriteLine ( " ;") ;
128+ writer . WriteLine ( $ " { cache_setter_end } ;") ;
105129 return ;
106130 }
107131
108132 if ( field . Symbol . IsArray ) {
109- writer . WriteLine ( $ "return global::Android.Runtime.JavaArray<{ opt . GetOutputName ( field . Symbol . ElementType ) } >.FromJniHandle (__v.Handle, JniHandleOwnership.TransferLocalRef);") ;
133+ writer . WriteLine ( $ "return { cache_setter } global::Android.Runtime.JavaArray<{ opt . GetOutputName ( field . Symbol . ElementType ) } >.FromJniHandle (__v.Handle, JniHandleOwnership.TransferLocalRef){ cache_setter_end } ;") ;
110134 } else if ( field . Symbol . NativeType != field . Symbol . FullName ) {
111- writer . WriteLine ( $ "return { field . Symbol . ReturnCast } { ( field . Symbol . FromNative ( opt , invokeType != "Object" ? "__v" : "__v.Handle" , true ) + opt . GetNullForgiveness ( field ) ) } ;") ;
135+ writer . WriteLine ( $ "return { cache_setter } { field . Symbol . ReturnCast } { ( field . Symbol . FromNative ( opt , invokeType != "Object" ? "__v" : "__v.Handle" , true ) + opt . GetNullForgiveness ( field ) ) } { cache_setter_end } ;") ;
112136 } else {
113- writer . WriteLine ( "return __v;" ) ;
137+ writer . WriteLine ( $ "return { cache_setter } __v{ cache_setter_end } ;") ;
114138 }
115139 }
116140
0 commit comments