diff --git a/src/PolyType/ReflectionProvider/ReflectionTypeShapeProvider.cs b/src/PolyType/ReflectionProvider/ReflectionTypeShapeProvider.cs index 64a0febb..2c10cfc7 100644 --- a/src/PolyType/ReflectionProvider/ReflectionTypeShapeProvider.cs +++ b/src/PolyType/ReflectionProvider/ReflectionTypeShapeProvider.cs @@ -294,13 +294,13 @@ private IUnionTypeShape CreateUnionTypeShape(Type unionType, FSharpUnionInfo? fS return (IUnionTypeShape)Activator.CreateInstance(fsharpUnionTypeTy, fSharpUnionInfo, this, options)!; } - List derivedTypeAttributes = unionType.GetCustomAttributes().ToList(); + List derivedTypeAttributes = unionType.GetCustomAttributes(inherit: false).ToList(); // Honor KnownTypeAttribute annotations only when no DerivedTypeShapeAttribute is present, // which takes precedence over KnownTypeAttribute. if (derivedTypeAttributes.Count == 0) { - var mappedKnownTypeAttributes = unionType.GetCustomAttributes() + var mappedKnownTypeAttributes = unionType.GetCustomAttributes(inherit: false) .Select(attr => { if (attr.Type is null) @@ -308,8 +308,9 @@ private IUnionTypeShape CreateUnionTypeShape(Type unionType, FSharpUnionInfo? fS throw new NotSupportedException("KnownTypeAttribute annotations using methods are not supported."); } - return new DerivedTypeShapeAttribute(attr.Type); - }); + return attr.Type; + }) + .Select(t => new DerivedTypeShapeAttribute(t)); derivedTypeAttributes.AddRange(mappedKnownTypeAttributes); } diff --git a/tests/PolyType.Tests/DataContractShapeTests.cs b/tests/PolyType.Tests/DataContractShapeTests.cs index 79929bed..4ff8d850 100644 --- a/tests/PolyType.Tests/DataContractShapeTests.cs +++ b/tests/PolyType.Tests/DataContractShapeTests.cs @@ -89,9 +89,19 @@ public void KnownTypeAttribute_ReportsUnionShape() { var shape = Assert.IsType(providerUnderTest.Provider.GetTypeShape(typeof(Animal)), exactMatch: false); - Assert.Equal(2, shape.UnionCases.Count); + Assert.Equal(3, shape.UnionCases.Count); Assert.Contains(shape.UnionCases, c => c.UnionCaseType.Type == typeof(Dog)); Assert.Contains(shape.UnionCases, c => c.UnionCaseType.Type == typeof(Cat)); + Assert.Contains(shape.UnionCases, c => c.UnionCaseType.Type == typeof(PersianCat)); + } + + [Fact] + public void KnownTypeAttribute_DerivedTypesReportsUnionShape() + { + var shape = Assert.IsType(providerUnderTest.Provider.GetTypeShape(typeof(Cat)), exactMatch: false); + + Assert.Single(shape.UnionCases); + Assert.Contains(shape.UnionCases, c => c.UnionCaseType.Type == typeof(PersianCat)); } [Fact] @@ -193,6 +203,7 @@ public enum ContractEnum [DataContract] [KnownType(typeof(Dog))] [KnownType(typeof(Cat))] + [KnownType(typeof(PersianCat))] public partial class Animal { [DataMember(Order = 0)] public string? Name { get; set; } @@ -204,12 +215,21 @@ public class Dog : Animal [DataMember(Order = 1)] public bool Barks { get; set; } } + [GenerateShape] [DataContract] - public class Cat : Animal + [KnownType(typeof(PersianCat))] + public partial class Cat : Animal { [DataMember(Order = 1)] public int Lives { get; set; } } + [DataContract] + public class PersianCat : Cat + { + [DataMember(Order = 2)] public string? FurColor { get; set; } + [DataMember(Order = 3)] public bool RequiresGrooming { get; set; } + } + [GenerateShape] [KnownType(typeof(DogNoDataContract))] public partial class AnimalNoDataContract