@@ -41,6 +41,11 @@ public sealed partial class ObservableAsPropertyGenerator
41
41
attributeData . TryGetNamedArgument ( "UseProtected" , out bool useProtected ) ;
42
42
var useProtectedModifier = useProtected ? "protected" : "private" ;
43
43
44
+ token . ThrowIfCancellationRequested ( ) ;
45
+
46
+ // Get the can ReadOnly member, if any
47
+ attributeData . TryGetNamedArgument ( "ReadOnly" , out bool ? isReadonly ) ;
48
+
44
49
token . ThrowIfCancellationRequested ( ) ;
45
50
var compilation = context . SemanticModel . Compilation ;
46
51
@@ -106,6 +111,7 @@ public sealed partial class ObservableAsPropertyGenerator
106
111
isNullableType ,
107
112
false ,
108
113
propertyAttributes ,
114
+ string . Empty ,
109
115
useProtectedModifier ,
110
116
initialValue ) ,
111
117
diagnostics . ToImmutable ( ) ) ;
@@ -131,6 +137,7 @@ public sealed partial class ObservableAsPropertyGenerator
131
137
132
138
var observableType = string . Empty ;
133
139
var isNullableType = false ;
140
+ var isPartialProperty = false ;
134
141
135
142
token . ThrowIfCancellationRequested ( ) ;
136
143
context . GetForwardedAttributes (
@@ -173,10 +180,9 @@ public sealed partial class ObservableAsPropertyGenerator
173
180
174
181
token . ThrowIfCancellationRequested ( ) ;
175
182
176
- var inheritance = propertySymbol . IsVirtual ? " virtual" : propertySymbol . IsOverride ? " override" : string . Empty ;
183
+ isPartialProperty = true ;
177
184
178
- // Get the can ReadOnly member, if any
179
- attributeData . TryGetNamedArgument ( "ReadOnly" , out bool ? isReadonly ) ;
185
+ var inheritance = propertySymbol . IsVirtual ? " virtual" : propertySymbol . IsOverride ? " override" : string . Empty ;
180
186
181
187
token . ThrowIfCancellationRequested ( ) ;
182
188
@@ -215,6 +221,12 @@ public sealed partial class ObservableAsPropertyGenerator
215
221
}
216
222
#endif
217
223
224
+ var isReadOnlyString = string . Empty ;
225
+ if ( isPartialProperty )
226
+ {
227
+ isReadOnlyString = isReadonly == false ? string . Empty : "readonly" ;
228
+ }
229
+
218
230
// Get the containing type info
219
231
var targetInfo = TargetInfo . From ( propertySymbol . ContainingType ) ;
220
232
@@ -229,6 +241,7 @@ public sealed partial class ObservableAsPropertyGenerator
229
241
isNullableType ,
230
242
true ,
231
243
propertyAttributes ,
244
+ isReadOnlyString ,
232
245
useProtectedModifier ,
233
246
initialValue ) ,
234
247
diagnostics . ToImmutable ( ) ) ;
@@ -307,12 +320,20 @@ private static string GetPropertySyntax(ObservableMethodInfo propertyInfo)
307
320
propertyType = propertyInfo . PartialPropertyType ;
308
321
}
309
322
323
+ var helperTypeName = $ "{ propertyInfo . AccessModifier } ReactiveUI.ObservableAsPropertyHelper<{ propertyType } >?";
324
+
325
+ // If the property is readonly, we need to change the helper to be non-nullable
326
+ if ( propertyInfo . IsReadOnly == "readonly" )
327
+ {
328
+ helperTypeName = $ "{ propertyInfo . AccessModifier } readonly ReactiveUI.ObservableAsPropertyHelper<{ propertyType } >";
329
+ }
330
+
310
331
return $$ """
311
332
/// <inheritdoc cref="{{ propertyInfo . PropertyName }} "/>
312
333
private {{ propertyType }} {{ getterFieldIdentifierName }} {{ initialValue }} ;
313
334
314
335
/// <inheritdoc cref="{{ getterFieldIdentifierName }} Helper"/>
315
- {{ propertyInfo . AccessModifier }} ReactiveUI.ObservableAsPropertyHelper< {{ propertyType }} >? {{ getterFieldIdentifierName }} Helper;
336
+ {{ helperTypeName }} {{ getterFieldIdentifierName }} Helper;
316
337
317
338
/// <inheritdoc cref="{{ getterFieldIdentifierName }} "/>
318
339
{{ propertyAttributes }}
0 commit comments