@@ -23,13 +23,6 @@ private NotSerializedException(SerializationInfo info, StreamingContext context)
2323 override public void GetObjectData ( SerializationInfo info , StreamingContext context ) => base . GetObjectData ( info , context ) ;
2424 }
2525
26-
27- // empty attribute to mark classes created by the "non-serializer" so we don't loop-inherit
28- // on multiple cycles of de/serialization
29- [ System . AttributeUsage ( System . AttributeTargets . All , Inherited = false , AllowMultiple = true ) ]
30- [ System . Serializable ]
31- sealed class PyNet_NotSerializedAttribute : System . Attribute { }
32-
3326 [ Serializable ]
3427 internal static class NonSerializedTypeBuilder
3528 {
@@ -40,7 +33,12 @@ internal static class NonSerializedTypeBuilder
4033 AppDomain . CurrentDomain . DefineDynamicAssembly ( nonSerializedAssemblyName , AssemblyBuilderAccess . Run ) ;
4134 internal static ModuleBuilder moduleBuilder = assemblyForNonSerializedClasses . DefineDynamicModule ( "NotSerializedModule" ) ;
4235 internal static HashSet < string > dontReimplementMethods = new ( ) { "Finalize" , "Dispose" , "GetType" , "ReferenceEquals" , "GetHashCode" , "Equals" } ;
43- const string notSerializedSuffix = "_NotSerialized" ;
36+ internal const string notSerializedSuffix = "_NotSerialized" ;
37+ // dummy field name to mark classes created by the "non-serializer" so we don't loop-inherit
38+ // on multiple cycles of de/serialization. We use a static field instead of an attribute
39+ // becaues of a bug in mono. Put a space in the name so users will be extremely unlikely
40+ // to create a field with the same name.
41+ internal const string notSerializedFieldName = "__PyNet NonSerialized" ;
4442
4543 private static Func < Type , TypeAttributes , bool > hasVisibility = ( tp , attr ) => ( tp . Attributes & TypeAttributes . VisibilityMask ) == attr ;
4644 private static Func < Type , bool > isNestedType = ( tp ) => hasVisibility ( tp , TypeAttributes . NestedPrivate ) || hasVisibility ( tp , TypeAttributes . NestedPublic ) || hasVisibility ( tp , TypeAttributes . NestedFamily ) || hasVisibility ( tp , TypeAttributes . NestedAssembly ) ;
@@ -96,14 +94,13 @@ static void FillTypeMethods(TypeBuilder tb)
9694
9795 static string MakeName ( Type tp )
9896 {
99- const string suffix = "_NotSerialized" ;
100- string @out = tp . Name + suffix ;
97+ string @out = tp . Name + notSerializedSuffix ;
10198 var parentType = tp . DeclaringType ;
10299 while ( parentType is not null )
103100 {
104101 // If we have a nested class, we need the whole nester/nestee
105102 // chain with the suffix for each.
106- @out = parentType . Name + suffix + "+" + @out ;
103+ @out = parentType . Name + notSerializedSuffix + "+" + @out ;
107104 parentType = parentType . DeclaringType ;
108105 }
109106 return @out ;
@@ -151,7 +148,7 @@ static string MakeName(Type tp)
151148 }
152149
153150 TypeBuilder tb = GetTypeBuilder ( baseType ) ;
154- SetNonSerialiedAttr ( tb ) ;
151+ SetNonSerializedAttr ( tb ) ;
155152 FillTypeMethods ( tb ) ;
156153
157154 var nestedtypes = baseType . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ) ;
@@ -172,7 +169,7 @@ static string MakeName(Type tp)
172169 foreach ( var builder in nestedBuilders )
173170 {
174171 FillTypeMethods ( builder ) ;
175- SetNonSerialiedAttr ( builder ) ;
172+ SetNonSerializedAttr ( builder ) ;
176173 builder . CreateType ( ) ;
177174 }
178175 return outTp ;
@@ -207,11 +204,18 @@ private static void ImplementEqualityAndHash(TypeBuilder tb)
207204 equalsIlGen . Emit ( OpCodes . Ret ) ;
208205 }
209206
210- private static void SetNonSerialiedAttr ( TypeBuilder tb )
207+ private static void SetNonSerializedAttr ( TypeBuilder tb )
211208 {
212- ConstructorInfo attrCtorInfo = typeof ( PyNet_NotSerializedAttribute ) . GetConstructor ( new Type [ ] { } ) ;
213- CustomAttributeBuilder attrBuilder = new CustomAttributeBuilder ( attrCtorInfo , new object [ ] { } ) ;
214- tb . SetCustomAttribute ( attrBuilder ) ;
209+ // Name of the function says we're adding an attribute, but for some
210+ // reason on Mono the attribute is not added, and no exceptions are
211+ // thrown.
212+ tb . DefineField ( notSerializedFieldName , typeof ( int ) , FieldAttributes . Public | FieldAttributes . Static ) ;
213+ }
214+
215+ public static bool IsNonSerializedType ( Type tp )
216+ {
217+ return tp . GetField ( NonSerializedTypeBuilder . notSerializedFieldName , BindingFlags . Public | BindingFlags . Static ) is not null ;
218+
215219 }
216220
217221 private static TypeBuilder GetTypeBuilder ( Type baseType )
@@ -325,7 +329,7 @@ public void GetObjectData(object obj, SerializationInfo info, StreamingContext c
325329
326330 MaybeType type = obj . GetType ( ) ;
327331
328- if ( type . Value . CustomAttributes . Any ( ( attr ) => attr . AttributeType == typeof ( PyNet_NotSerializedAttribute ) ) )
332+ if ( NonSerializedTypeBuilder . IsNonSerializedType ( type . Value ) )
329333 {
330334 // Don't serialize a _NotSerialized. Serialize the base type, and deserialize as a _NotSerialized
331335 type = type . Value . BaseType ;
0 commit comments