2626
2727namespace Doxense . Serialization . Json
2828{
29- using System . Reflection ;
29+ [ Flags ]
30+ public enum CrystalJsonMemberFlags
31+ {
32+ None = 0 ,
33+ SourceGenerated = 1 << 0 ,
34+ NotNull = 1 << 1 ,
35+ NonZeroDefault = 1 << 2 ,
36+ ReadOnly = 1 << 3 ,
37+ InitOnly = 1 << 4 ,
38+ Required = 1 << 5 ,
39+ Key = 1 << 6 ,
40+ }
3041
3142/// <summary>Structure that holds the cached serialization metadata for a field or property of a class or struct</summary>
3243[ DebuggerDisplay ( "Name={Name}, Type={Type}" ) ]
@@ -44,22 +55,22 @@ public sealed record CrystalJsonMemberDefinition
4455/// <remarks>Represent the original name in the c# code, while <see cref="Name"/> is the name in the JSON object</remarks>
4556public required string OriginalName { get ; init ; }
4657
58+ /// <summary>Flags for this member</summary>
59+ /// <returns>The flags are used by the various helper properties like <see cref="IsReadOnly"/>, <see cref="IsReadOnly"/> and so on</returns>
60+ public required CrystalJsonMemberFlags Flags { get ; init ; }
61+
4762/// <summary>Optional <see cref="JsonPropertyAttribute"/> attribute that was applied to this member</summary>
4863public JsonPropertyAttribute ? Attributes { get ; init ; }
49-
50- /// <summary>Original <see cref="PropertyInfo"/> or <see cref="FieldInfo"/> of the member in its declaring type</summary>
51- public required MemberInfo Member { get ; init ; }
64+ //REVIEW: this is only used by the writer to "remember" how to format enums inside a Dictionary (attribute set on the property that holds the dictionary)
65+ //TODO: get rid of this, and expose the settings directly on this type?
5266
5367/// <summary>If <see langword="true"/>, the field has a <see cref="DefaultValue"/> that is not the default for this type.</summary>
5468/// <remarks>This is <see langword="false"/> if the default is <see langword="null"/>, <see langword="false"/>, <see langword="0"/>, etc...</remarks>
55- public bool HasDefaultValue { get ; init ; }
69+ public bool HasDefaultValue => this . Flags . HasFlag ( CrystalJsonMemberFlags . NonZeroDefault ) ;
5670
5771/// <summary>Default value for this member (when it is missing)</summary>
5872public object ? DefaultValue { get ; init ; }
5973
60- /// <summary>Flag set to <see langword="true"/> when the member is read-only or init-only</summary>
61- public bool ReadOnly { get ; init ; }
62-
6374/// <summary>Func that can return the value of this member in an instance of the containing type</summary>
6475public required Func < object , object ? > Getter { get ; init ; }
6576
@@ -86,34 +97,8 @@ public sealed record CrystalJsonMemberDefinition
8697/// </code></remarks>
8798public Type ? NullableOfType { get ; init ; }
8899
89- /// <summary>The member cannot be null, or is annotated with <see cref="System.Diagnostics.CodeAnalysis.NotNullAttribute"/></summary>
90- /// <remarks>Examples: <code>
91- /// int Foo { get; ... } // IsNotNull == true
92- /// int? Foo { get; ... } // IsNotNull == false
93- /// string Foo { get; ... } // IsNotNull == true
94- /// string? Foo { get; ... } // IsNotNull == false
95- /// </code></remarks>
96- public bool IsNotNull { get ; init ; }
97-
98- /// <summary>The member if a reference type that is declared as nullable in its parent type</summary>
99- /// <remarks>Examples: <code>
100- /// int Foo { get; ... } // IsNullableRefType == false
101- /// int? Foo { get; ... } // IsNullableRefType == false
102- /// string Foo { get; ... } // IsNullableRefType == false
103- /// string? Foo { get; ... } // IsNullableRefType == true
104- /// </code></remarks>
105- public bool IsNullableRefType => ! this . IsNotNull && this . NullableOfType == null ;
106-
107- /// <summary>The member if a nullable value type</summary>
108- /// <remarks>Examples: <code>
109- /// int Foo { get; ... } // IsNullableValueType == false
110- /// int? Foo { get; ... } // IsNullableValueType == true
111- /// string Foo { get; ... } // IsNullableValueType == false
112- /// string? Foo { get; ... } // IsNullableValueType == false
113- /// </code></remarks>
114- public bool IsNullableValueType => this . NullableOfType != null ;
115-
116- public bool IsNonNullableValueType => this . NullableOfType == null && this . Type . IsValueType ;
100+ /// <summary>Flag set to <see langword="true"/> when the member is read-only or init-only</summary>
101+ public bool IsReadOnly => this . Flags . HasFlag ( CrystalJsonMemberFlags . ReadOnly ) ;
117102
118103/// <summary>The member has the required keyword and cannot be null</summary>
119104/// <remarks>Examples: <code>
@@ -124,7 +109,7 @@ public sealed record CrystalJsonMemberDefinition
124109/// required int Foo { get; ... } // IsRequired == true
125110/// required string Foo { get; ... } // IsRequired == true
126111/// </code></remarks>
127- public bool IsRequired { get ; init ; }
112+ public bool IsRequired => this . Flags . HasFlag ( CrystalJsonMemberFlags . Required ) ;
128113
129114/// <summary>The member has the <see cref="System.ComponentModel.DataAnnotations.KeyAttribute"/> attribute</summary>
130115/// <remarks>Examples: <code>
@@ -133,7 +118,7 @@ public sealed record CrystalJsonMemberDefinition
133118/// [Key]
134119/// int Id { get; ... } // IsKey == true
135120/// </code></remarks>
136- public bool IsKey { get ; init ; }
121+ public bool IsKey => this . Flags . HasFlag ( CrystalJsonMemberFlags . Key ) ;
137122
138123/// <summary>The member is a read-only field, or a property with an init-only setter</summary>
139124/// <remarks>Examples: <code>
@@ -144,7 +129,36 @@ public sealed record CrystalJsonMemberDefinition
144129/// readonly int Id; // IsInitOnly == true
145130/// int Id { get; init; } // IsInitOnly == true
146131/// </code></remarks>
147- public bool IsInitOnly { get ; init ; }
132+ public bool IsInitOnly => this . Flags . HasFlag ( CrystalJsonMemberFlags . InitOnly ) ;
133+
134+ /// <summary>The member cannot be null, or is annotated with <see cref="System.Diagnostics.CodeAnalysis.NotNullAttribute"/></summary>
135+ /// <remarks>Examples: <code>
136+ /// int Foo { get; ... } // IsNotNull == true
137+ /// int? Foo { get; ... } // IsNotNull == false
138+ /// string Foo { get; ... } // IsNotNull == true
139+ /// string? Foo { get; ... } // IsNotNull == false
140+ /// </code></remarks>
141+ public bool IsNotNull => this . Flags . HasFlag ( CrystalJsonMemberFlags . NotNull ) ;
142+
143+ /// <summary>The member if a reference type that is declared as nullable in its parent type</summary>
144+ /// <remarks>Examples: <code>
145+ /// int Foo { get; ... } // IsNullableRefType == false
146+ /// int? Foo { get; ... } // IsNullableRefType == false
147+ /// string Foo { get; ... } // IsNullableRefType == false
148+ /// string? Foo { get; ... } // IsNullableRefType == true
149+ /// </code></remarks>
150+ public bool IsNullableRefType => ! this . IsNotNull && this . NullableOfType == null ;
151+
152+ /// <summary>The member if a nullable value type</summary>
153+ /// <remarks>Examples: <code>
154+ /// int Foo { get; ... } // IsNullableValueType == false
155+ /// int? Foo { get; ... } // IsNullableValueType == true
156+ /// string Foo { get; ... } // IsNullableValueType == false
157+ /// string? Foo { get; ... } // IsNullableValueType == false
158+ /// </code></remarks>
159+ public bool IsNullableValueType => this . NullableOfType != null ;
160+
161+ public bool IsNonNullableValueType => this . NullableOfType == null && this . Type . IsValueType ;
148162
149163}
150164
0 commit comments