Skip to content

Commit

Permalink
fix: Cecil serialization inheritance cutoff with complex base types (#…
Browse files Browse the repository at this point in the history
…2457)

* fix: Cecil serialization inheritance cutoff with complex base types

* Add small summary of the loop
  • Loading branch information
Eideren authored Sep 22, 2024
1 parent ae92baa commit b6f16b8
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ private static void GenerateSerializerCode(ComplexSerializerRegistry registry, o

TypeReference parentType = null;
FieldDefinition parentSerializerField = null;
if (complexType.Value.ComplexSerializerProcessParentType)
if (complexType.Value.ComplexSerializerProcessParentType != null)
{
parentType = ResolveGenericsVisitor.Process(serializerType, type.BaseType);
parentType = complexType.Value.ComplexSerializerProcessParentType;
serializerType.Fields.Add(parentSerializerField = new FieldDefinition("parentSerializer", Mono.Cecil.FieldAttributes.Private, dataSerializerTypeRef.MakeGenericType(parentType)));

hash.Write("parent");
Expand Down Expand Up @@ -134,7 +134,7 @@ private static void GenerateSerializerCode(ComplexSerializerRegistry registry, o
// Add Initialize method
var initialize = new MethodDefinition("Initialize", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, assembly.MainModule.TypeSystem.Void);
initialize.Parameters.Add(new ParameterDefinition("serializerSelector", ParameterAttributes.None, serializerSelectorTypeRef));
if (complexType.Value.ComplexSerializerProcessParentType)
if (complexType.Value.ComplexSerializerProcessParentType != null)
{
initialize.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
initialize.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_1));
Expand Down Expand Up @@ -162,7 +162,7 @@ private static void GenerateSerializerCode(ComplexSerializerRegistry registry, o
serialize.Parameters.Add(new ParameterDefinition(parentParameter.Name, ParameterAttributes.None, assembly.MainModule.ImportReference(parentParameter.ParameterType)));
}

if (complexType.Value.ComplexSerializerProcessParentType)
if (complexType.Value.ComplexSerializerProcessParentType != null)
{
serialize.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
serialize.Body.Instructions.Add(Instruction.Create(OpCodes.Ldfld, parentSerializerField.MakeGeneric(genericParameters)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,19 @@ public SerializableTypeInfo GenerateSerializer(TypeReference type, bool force =
private void ProcessComplexSerializerMembers(TypeReference type, SerializableTypeInfo serializableTypeInfo, string profile = "Default")
{
// Process base type (for complex serializers)
// If it's a closed type and there is a serializer, we'll serialize parent
SerializableTypeInfo parentSerializableTypeInfo;
var parentType = ResolveGenericsVisitor.Process(type, type.Resolve().BaseType);
if (!parentType.ContainsGenericParameter() && (parentSerializableTypeInfo = GenerateSerializer(parentType, false, profile)) != null &&
parentSerializableTypeInfo.SerializerType != null)
// Check if we have any serializable closed base type and collect it to pass it over to GenerateSerializerCode later,
// who'll ensure the generated serializer for this type calls into its base types' serializer
for (var baseType = type; (baseType = ResolveGenericsVisitor.Process(baseType, baseType.Resolve().BaseType)) != null;)
{
serializableTypeInfo.ComplexSerializerProcessParentType = true;
if (baseType.ContainsGenericParameter())
continue; // ResolveGenericsVisitor failed, the type it returned is not closed, we can't serialize it

var parentSerializableTypeInfo = GenerateSerializer(baseType, false, profile);
if (parentSerializableTypeInfo?.SerializerType != null)
{
serializableTypeInfo.ComplexSerializerProcessParentType = baseType;
break;
}
}

// Process members
Expand Down Expand Up @@ -580,9 +586,9 @@ internal class SerializableTypeInfo
public bool ComplexSerializer;

/// <summary>
/// True if it's a complex serializer and its base class should be serialized too.
/// Not null if it's a complex serializer and its base class should be serialized too.
/// </summary>
public bool ComplexSerializerProcessParentType;
public TypeReference ComplexSerializerProcessParentType;

public SerializableTypeInfo(TypeReference serializerType, bool local, DataSerializerGenericMode mode = DataSerializerGenericMode.None)
{
Expand Down

0 comments on commit b6f16b8

Please sign in to comment.