77using System . Collections . Generic ;
88using System . Diagnostics ;
99using System . Runtime . CompilerServices ;
10+ using System . Runtime . Serialization ;
1011using System . Threading ;
1112
1213using IronPython . Runtime . Operations ;
@@ -33,7 +34,8 @@ namespace IronPython.Runtime {
3334 /// the buckets and then calls a static helper function to do the read from the bucket
3435 /// array to ensure that readers are not seeing multiple bucket arrays.
3536 /// </summary>
36- internal sealed class CommonDictionaryStorage : DictionaryStorage {
37+ [ Serializable ]
38+ internal sealed class CommonDictionaryStorage : DictionaryStorage , ISerializable , IDeserializationCallback {
3739 private int [ ] _indices ;
3840 private List < Bucket > _buckets ;
3941 private int _count ;
@@ -117,6 +119,16 @@ private CommonDictionaryStorage(int[] indices, List<Bucket> buckets, int count,
117119 _eqFunc = eqFunc ;
118120 }
119121
122+ #if FEATURE_SERIALIZATION
123+ private CommonDictionaryStorage ( SerializationInfo info , StreamingContext context ) {
124+ // Remember the serialization info, we'll deserialize when we get the callback. This
125+ // enables special types like DBNull.Value to successfully be deserialized inside of us. We
126+ // store the serialization info in a special bucket so we don't have an extra field just for
127+ // serialization.
128+ _buckets = new List < Bucket > { new Bucket ( null , info , 0 ) } ;
129+ }
130+ #endif
131+
120132 public override void Add ( ref DictionaryStorage storage , object key , object value )
121133 => Add ( key , value ) ;
122134
@@ -651,5 +663,31 @@ private static bool TupleEquals(object o1, object o2)
651663 private static bool GenericEquals ( object o1 , object o2 ) => PythonOps . EqualRetBool ( o1 , o2 ) ;
652664
653665 #endregion
666+
667+ #if FEATURE_SERIALIZATION
668+ #region ISerializable Members
669+
670+ public void GetObjectData ( SerializationInfo info , StreamingContext context ) {
671+ info . AddValue ( "buckets" , GetItems ( ) ) ;
672+ }
673+
674+ void IDeserializationCallback . OnDeserialization ( object sender ) {
675+ if ( _indices is not null ) {
676+ // we've received multiple OnDeserialization callbacks, only
677+ // deserialize after the 1st one
678+ return ;
679+ }
680+
681+ var info = ( SerializationInfo ) _buckets [ 0 ] . Value ;
682+ _buckets . Clear ( ) ;
683+
684+ var buckets = ( List < KeyValuePair < object , object > > ) info . GetValue ( "buckets" , typeof ( List < KeyValuePair < object , object > > ) ) ;
685+ foreach ( KeyValuePair < object , object > kvp in buckets ) {
686+ AddNoLock ( kvp . Key , kvp . Value ) ;
687+ }
688+ }
689+
690+ #endregion
691+ #endif
654692 }
655693}
0 commit comments