@@ -19,6 +19,20 @@ internal sealed class OrderedDictionaryObjectModel
1919 public OrderedDictionary < string , object > Items { get ; set ; } = new ( ) ;
2020}
2121
22+ internal sealed class OrderedDictionaryReferenceModel
23+ {
24+ public OrderedDictionary < string , int > ? Primary { get ; set ; }
25+
26+ public OrderedDictionary < string , int > ? Secondary { get ; set ; }
27+ }
28+
29+ internal sealed class OrderedDictionaryGenericReferenceModel
30+ {
31+ public OrderedDictionary < int , string > ? Primary { get ; set ; }
32+
33+ public OrderedDictionary < int , string > ? Secondary { get ; set ; }
34+ }
35+
2236[ YamlSourceGenerationOptions ( PropertyNamingPolicy = JsonKnownNamingPolicy . CamelCase ) ]
2337[ YamlSerializable ( typeof ( OrderedDictionary < string , int > ) ) ]
2438[ YamlSerializable ( typeof ( OrderedDictionary < string , string > ) ) ]
@@ -128,6 +142,70 @@ public void Reflection_RoundTrip_PreservesOrder()
128142 CollectionAssert . AreEqual ( originalKeys , resultKeys ) ;
129143 }
130144
145+ [ TestMethod ]
146+ public void Reflection_RoundTrip_StringKeyOrderedDictionary_ShouldPreserveSharedReferences ( )
147+ {
148+ var shared = new OrderedDictionary < string , int >
149+ {
150+ { "zebra" , 1 } ,
151+ { "apple" , 2 } ,
152+ } ;
153+
154+ var payload = new OrderedDictionaryReferenceModel
155+ {
156+ Primary = shared ,
157+ Secondary = shared ,
158+ } ;
159+
160+ var options = new YamlSerializerOptions { ReferenceHandling = YamlReferenceHandling . Preserve } ;
161+ var yaml = YamlSerializer . Serialize ( payload , options ) ;
162+
163+ var anchor = ExtractAnchor ( yaml , "Primary: &" ) ;
164+ StringAssert . Contains ( yaml , $ "Secondary: *{ anchor } ") ;
165+
166+ var result = YamlSerializer . Deserialize < OrderedDictionaryReferenceModel > ( yaml , options ) ;
167+
168+ Assert . IsNotNull ( result ) ;
169+ Assert . IsNotNull ( result . Primary ) ;
170+ Assert . IsNotNull ( result . Secondary ) ;
171+ Assert . IsTrue ( ReferenceEquals ( result . Primary , result . Secondary ) ) ;
172+
173+ var keys = new List < string > ( result . Primary . Keys ) ;
174+ CollectionAssert . AreEqual ( new [ ] { "zebra" , "apple" } , keys ) ;
175+ }
176+
177+ [ TestMethod ]
178+ public void Reflection_RoundTrip_GenericKeyOrderedDictionary_ShouldPreserveSharedReferences ( )
179+ {
180+ var shared = new OrderedDictionary < int , string >
181+ {
182+ { 3 , "three" } ,
183+ { 1 , "one" } ,
184+ } ;
185+
186+ var payload = new OrderedDictionaryGenericReferenceModel
187+ {
188+ Primary = shared ,
189+ Secondary = shared ,
190+ } ;
191+
192+ var options = new YamlSerializerOptions { ReferenceHandling = YamlReferenceHandling . Preserve } ;
193+ var yaml = YamlSerializer . Serialize ( payload , options ) ;
194+
195+ var anchor = ExtractAnchor ( yaml , "Primary: &" ) ;
196+ StringAssert . Contains ( yaml , $ "Secondary: *{ anchor } ") ;
197+
198+ var result = YamlSerializer . Deserialize < OrderedDictionaryGenericReferenceModel > ( yaml , options ) ;
199+
200+ Assert . IsNotNull ( result ) ;
201+ Assert . IsNotNull ( result . Primary ) ;
202+ Assert . IsNotNull ( result . Secondary ) ;
203+ Assert . IsTrue ( ReferenceEquals ( result . Primary , result . Secondary ) ) ;
204+
205+ var keys = new List < int > ( result . Primary . Keys ) ;
206+ CollectionAssert . AreEqual ( new [ ] { 3 , 1 } , keys ) ;
207+ }
208+
131209 [ TestMethod ]
132210 public void Reflection_Deserialize_NullValue ( )
133211 {
@@ -284,4 +362,18 @@ public void SourceGen_Deserialize_WithCamelCaseNaming()
284362 Assert . IsNotNull ( result ) ;
285363 Assert . AreEqual ( 2 , result . Count ) ;
286364 }
365+
366+ private static string ExtractAnchor ( string yaml , string prefix )
367+ {
368+ var anchorStart = yaml . IndexOf ( prefix , StringComparison . Ordinal ) ;
369+ Assert . IsTrue ( anchorStart >= 0 , $ "Expected '{ prefix } ' in YAML.") ;
370+ anchorStart += prefix . Length ;
371+
372+ var anchorEnd = yaml . IndexOf ( '\n ' , anchorStart ) ;
373+ Assert . IsTrue ( anchorEnd > anchorStart , $ "Expected an anchor after '{ prefix } '.") ;
374+
375+ var anchor = yaml . Substring ( anchorStart , anchorEnd - anchorStart ) . Trim ( ) ;
376+ Assert . AreNotEqual ( string . Empty , anchor ) ;
377+ return anchor ;
378+ }
287379}
0 commit comments