Skip to content

Commit

Permalink
Correctly handle inheritance of EntrySerializeAttributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Toxantron committed Oct 12, 2023
1 parent e2dcc8a commit 6948a5d
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 40 deletions.
17 changes: 0 additions & 17 deletions src/Moryx.Resources.Samples/DocumentManager.cs

This file was deleted.

6 changes: 0 additions & 6 deletions src/Moryx/Serialization/EntryConvert/EntryConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,6 @@ public static Entry EncodeObject(object instance, ICustomSerialization customSer
var propertyType = property.PropertyType;
if (propertyType == instanceType)
continue;
if(propertyType == typeof(Object))
{
var propertyValue = property.GetValue(instance);
if (propertyValue != null && propertyValue?.GetType() == instanceType)
continue;
}

var convertedProperty = EncodeProperty(property, customSerialization);

Expand Down
39 changes: 24 additions & 15 deletions src/Moryx/Serialization/EntrySerializeSerialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public EntrySerializeSerialization(Type filterBaseType)
public override IEnumerable<ConstructorInfo> GetConstructors(Type sourceType)
{
var constructors = from ctor in base.GetConstructors(sourceType)
let mode = EvaluateSerializeMode(ctor)
where mode.HasValue && mode.Value == EntrySerializeMode.Always
select ctor;
let mode = EvaluateSerializeMode(ctor)
where mode.HasValue && mode.Value == EntrySerializeMode.Always
select ctor;

return constructors;
}
Expand All @@ -54,9 +54,9 @@ public override IEnumerable<MethodInfo> GetMethods(Type sourceType)
{
var methods = sourceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(m => !m.IsSpecialName);
methods = from method in methods
let mode = EvaluateSerializeMode(method)
where mode.HasValue && mode.Value == EntrySerializeMode.Always
select method;
let mode = EvaluateSerializeMode(method)
where mode.HasValue && mode.Value == EntrySerializeMode.Always
select method;

return methods;
}
Expand All @@ -66,14 +66,6 @@ public override IEnumerable<PropertyInfo> GetProperties(Type sourceType)
{
var properties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(BasePropertyFilter).Where(ExplicitPropertyFilter).ToArray();
var attributeOnClass = sourceType.GetCustomAttribute<EntrySerializeAttribute>(false);
var attributeOnClassOrBaseClass = sourceType.GetCustomAttribute<EntrySerializeAttribute>(true);
// to-do: remove this in .net8 and use restriction on the EntrySerializeAttribute
//EntrySerialize property on both class and base class
if (attributeOnClass != null && attributeOnClassOrBaseClass != null)
{
properties = properties.Where(property => property.GetCustomAttribute<EntrySerializeAttribute>() != null).ToArray();
}
return EntrySerializeAttributeFilter(sourceType, properties);
}

Expand Down Expand Up @@ -154,6 +146,23 @@ private static IEnumerable<PropertyInfo> EntrySerializeAttributeFilter(Type sour
return properties;
}

/// <summary>
/// Iterate the inheritance tree and find lowest declaration of the attribute
/// </summary>
private static EntrySerializeMode? EvaluateSerializeMode(Type attributeProvider)
{
// If more than 1 is declared, determine the lowest definition as it takes precedence
// For each declaration check assignability to determine lower type
var currentType = attributeProvider;
EntrySerializeAttribute lowestDeclaration = null;
while (currentType != typeof(object))
{
lowestDeclaration = currentType.GetCustomAttribute<EntrySerializeAttribute>(false) ?? lowestDeclaration;
currentType = currentType.BaseType;
}
return lowestDeclaration?.Mode;
}

/// <summary>
/// Checks if the <see cref="EntrySerializeAttribute"/> is existent and activated
/// </summary>
Expand All @@ -168,7 +177,7 @@ private static PropertyMode EvaluateSerializeMode(PropertyInfo property)
return new PropertyMode
{
Property = property,
Mode = EvaluateSerializeMode((ICustomAttributeProvider)property)
Mode = property.GetCustomAttribute<EntrySerializeAttribute>(true)?.Mode
};
}

Expand Down
2 changes: 0 additions & 2 deletions src/Tests/Moryx.Tests/Serialization/EntrySerializeDummies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ public class EntrySerialize_AlwaysClassAlwaysMember
[EntrySerialize]
public int Property2 { get; set; }

public object Property => this;

[EntrySerialize]
public EntrySerialize_AlwaysClassAlwaysMember AnotherProperty { get; set; }
internal IExplicitInterface ExplicitInterface { get; }
Expand Down

0 comments on commit 6948a5d

Please sign in to comment.