domaindrivendev / Swashbuckle.AspNetCore

Swagger tools for documenting API's built on ASP.NET Core
MIT License
5.25k stars 1.31k forks source link

[Question]: Polymorphism DiscriminatorValueSelector work with JsonDerivedTypeAttribute #2948

Open huiyuanai709 opened 4 months ago

huiyuanai709 commented 4 months ago

What are you wanting to achieve?

Try to polymorphism work with source generator JsonDerivedTypeAttribute. The DiscriminatorValueSelector func only have subClass info

public Func<Type, string> DiscriminatorValueSelector { get; set; }

but the JsonDerivedTypeAttribute is on the baseClass

builder.Services.AddSwaggerGen(options =>
{
    options.SchemaGeneratorOptions.UseOneOfForPolymorphism = true;
    options.SchemaGeneratorOptions.SubTypesSelector = baseType =>
        baseType.GetCustomAttributes<JsonDerivedTypeAttribute>().Select(x => x.DerivedType);
    options.SelectDiscriminatorNameUsing(baseType => baseType.GetCustomAttribute<JsonPolymorphicAttribute>()?.TypeDiscriminatorPropertyName ?? "$type");
    options.SelectDiscriminatorValueUsing(); // todo
});

image

What code or approach do you have so far?

var discriminatorValue = _generatorOptions.DiscriminatorValueSelector(knownTypeDataContract.UnderlyingType)

at https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/a97c53fd4dfe1a2ca2e2607959cf6c002b02c2e0/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGenerator.cs#L473

Additional context

No response

huiyuanai709 commented 4 months ago

Now I use the Approach to get TypeDiscriminator

builder.Services.AddSwaggerGen(options =>
{
    options.SchemaGeneratorOptions.UseOneOfForPolymorphism = true;
    options.SchemaGeneratorOptions.SubTypesSelector = baseType =>
        baseType.GetCustomAttributes<JsonDerivedTypeAttribute>().Select(x => x.DerivedType);
    options.SelectDiscriminatorNameUsing(baseType => baseType.GetCustomAttribute<JsonPolymorphicAttribute>()?.TypeDiscriminatorPropertyName ?? "$type");

    Type? SearchParentRecursive<T>(Type type) where T : Attribute
    {
        if(type.BaseType is null || type == typeof(object))
        {
            return null;
        }

        var attribute = type.BaseType.GetCustomAttribute<T>();
        if (attribute is null)
        {
            return SearchParentRecursive<T>(type.BaseType);
        }

        return type.BaseType;
    }
    options.SelectDiscriminatorValueUsing(subClass => SearchParentRecursive<JsonPolymorphicAttribute>(subClass)!.GetCustomAttributes<JsonDerivedTypeAttribute>().FirstOrDefault(x => x.DerivedType == subClass)!.TypeDiscriminator?.ToString());
});