Deduplicate property overrides; Shipping carrier nullable

- Fix property enumeration to dedupe overridden/shadowed properties, ensuring only the most-derived is included (affects serialization and schema).
- Update TOON_ISSUES.md: close duplicate property issue, document root cause and resolution.
- Make CargoPartnerId nullable in Shipping and IShipping; clarify ToonDescription for carrier/truck/trailer fields.
- Refine ShippingDocument ToonDescription for clarity.
- Minor null-safety and style cleanup in GridShipping.razor.
This commit is contained in:
Loretta 2026-05-31 14:52:40 +02:00
parent 5e06f3e122
commit d8a577024a
2 changed files with 20 additions and 10 deletions

View File

@ -363,14 +363,21 @@ public abstract class TypeMetadataBase
[UnconditionalSuppressMessage("Trimming", "IL2080",
Justification = "Same as IL2070 — currentType variable starts DAMs-annotated but loses annotation "
+ "through the BaseType reassignment in the loop.")]
private static List<PropertyInfo> BuildPropertyList(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type,
bool requiresWrite)
private static List<PropertyInfo> BuildPropertyList([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, bool requiresWrite)
{
// Collect properties from inheritance hierarchy (derived -> base order)
// Sorted alphabetically for deterministic property index ordering
var allProperties = new List<PropertyInfo>();
// Dedup by name across inheritance levels. An overridden (or 'new'-shadowed) property is
// declared at EVERY level it appears in, so BindingFlags.DeclaredOnly returns it once per
// level — without this guard the derived AND base PropertyInfo would both be collected
// (duplicate wire field on the runtime path; duplicate @types entry in Toon). The derived->base
// walk means the most-derived declaration is seen first and wins. Mirrors the SGen path
// (AcBinarySourceGenerator.GetAllSerializablePropertySymbols) so the runtime and generated
// property orders stay bit-identical.
var seen = new HashSet<string>(StringComparer.Ordinal);
for (var currentType = type; currentType != null && currentType != typeof(object); currentType = currentType.BaseType)
{
// Get properties declared at this level only
@ -379,7 +386,8 @@ public abstract class TypeMetadataBase
.Where(p => p.CanRead &&
(!requiresWrite || p.CanWrite) &&
p.GetIndexParameters().Length == 0 &&
!IsUnsupportedPropertyType(p.PropertyType))
!IsUnsupportedPropertyType(p.PropertyType) &&
seen.Add(p.Name))
.OrderBy(static p => p.Name, StringComparer.Ordinal);
allProperties.AddRange(levelProperties);

File diff suppressed because one or more lines are too long