7
7
using System . Collections . Generic ;
8
8
using System . Diagnostics ;
9
9
using System . Runtime . CompilerServices ;
10
+ using System . Runtime . Serialization ;
10
11
using System . Threading ;
11
12
12
13
using IronPython . Runtime . Operations ;
@@ -33,7 +34,8 @@ namespace IronPython.Runtime {
33
34
/// the buckets and then calls a static helper function to do the read from the bucket
34
35
/// array to ensure that readers are not seeing multiple bucket arrays.
35
36
/// </summary>
36
- internal sealed class CommonDictionaryStorage : DictionaryStorage {
37
+ [ Serializable ]
38
+ internal sealed class CommonDictionaryStorage : DictionaryStorage , ISerializable , IDeserializationCallback {
37
39
private int [ ] _indices ;
38
40
private List < Bucket > _buckets ;
39
41
private int _count ;
@@ -117,6 +119,16 @@ private CommonDictionaryStorage(int[] indices, List<Bucket> buckets, int count,
117
119
_eqFunc = eqFunc ;
118
120
}
119
121
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
+
120
132
public override void Add ( ref DictionaryStorage storage , object key , object value )
121
133
=> Add ( key , value ) ;
122
134
@@ -651,5 +663,31 @@ private static bool TupleEquals(object o1, object o2)
651
663
private static bool GenericEquals ( object o1 , object o2 ) => PythonOps . EqualRetBool ( o1 , o2 ) ;
652
664
653
665
#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
654
692
}
655
693
}
0 commit comments