@@ -23,13 +23,6 @@ private NotSerializedException(SerializationInfo info, StreamingContext context)
23
23
override public void GetObjectData ( SerializationInfo info , StreamingContext context ) => base . GetObjectData ( info , context ) ;
24
24
}
25
25
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
-
33
26
[ Serializable ]
34
27
internal static class NonSerializedTypeBuilder
35
28
{
@@ -40,7 +33,12 @@ internal static class NonSerializedTypeBuilder
40
33
AppDomain . CurrentDomain . DefineDynamicAssembly ( nonSerializedAssemblyName , AssemblyBuilderAccess . Run ) ;
41
34
internal static ModuleBuilder moduleBuilder = assemblyForNonSerializedClasses . DefineDynamicModule ( "NotSerializedModule" ) ;
42
35
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" ;
44
42
45
43
private static Func < Type , TypeAttributes , bool > hasVisibility = ( tp , attr ) => ( tp . Attributes & TypeAttributes . VisibilityMask ) == attr ;
46
44
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)
96
94
97
95
static string MakeName ( Type tp )
98
96
{
99
- const string suffix = "_NotSerialized" ;
100
- string @out = tp . Name + suffix ;
97
+ string @out = tp . Name + notSerializedSuffix ;
101
98
var parentType = tp . DeclaringType ;
102
99
while ( parentType is not null )
103
100
{
104
101
// If we have a nested class, we need the whole nester/nestee
105
102
// chain with the suffix for each.
106
- @out = parentType . Name + suffix + "+" + @out ;
103
+ @out = parentType . Name + notSerializedSuffix + "+" + @out ;
107
104
parentType = parentType . DeclaringType ;
108
105
}
109
106
return @out ;
@@ -151,7 +148,7 @@ static string MakeName(Type tp)
151
148
}
152
149
153
150
TypeBuilder tb = GetTypeBuilder ( baseType ) ;
154
- SetNonSerialiedAttr ( tb ) ;
151
+ SetNonSerializedAttr ( tb ) ;
155
152
FillTypeMethods ( tb ) ;
156
153
157
154
var nestedtypes = baseType . GetNestedTypes ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Static ) ;
@@ -172,7 +169,7 @@ static string MakeName(Type tp)
172
169
foreach ( var builder in nestedBuilders )
173
170
{
174
171
FillTypeMethods ( builder ) ;
175
- SetNonSerialiedAttr ( builder ) ;
172
+ SetNonSerializedAttr ( builder ) ;
176
173
builder . CreateType ( ) ;
177
174
}
178
175
return outTp ;
@@ -207,11 +204,18 @@ private static void ImplementEqualityAndHash(TypeBuilder tb)
207
204
equalsIlGen . Emit ( OpCodes . Ret ) ;
208
205
}
209
206
210
- private static void SetNonSerialiedAttr ( TypeBuilder tb )
207
+ private static void SetNonSerializedAttr ( TypeBuilder tb )
211
208
{
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
+
215
219
}
216
220
217
221
private static TypeBuilder GetTypeBuilder ( Type baseType )
@@ -325,7 +329,7 @@ public void GetObjectData(object obj, SerializationInfo info, StreamingContext c
325
329
326
330
MaybeType type = obj . GetType ( ) ;
327
331
328
- if ( type . Value . CustomAttributes . Any ( ( attr ) => attr . AttributeType == typeof ( PyNet_NotSerializedAttribute ) ) )
332
+ if ( NonSerializedTypeBuilder . IsNonSerializedType ( type . Value ) )
329
333
{
330
334
// Don't serialize a _NotSerialized. Serialize the base type, and deserialize as a _NotSerialized
331
335
type = type . Value . BaseType ;
0 commit comments