Last active
June 19, 2023 06:45
-
-
Save danslapman/5ac4f9bc6fd69b5d36f3fae15d940c94 to your computer and use it in GitHub Desktop.
Basic F# support for Swashbuckle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static class GenericExtensions | |
{ | |
public static void CopyProperties<T>(this T source, T destination) | |
{ | |
var props = source?.GetType().GetProperties(); | |
if (props == null) return; | |
foreach (var prop in props) | |
{ | |
prop.SetValue(destination, prop.GetValue(source)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.FSharp.Core; | |
using Microsoft.OpenApi.Models; | |
using Swashbuckle.AspNetCore.SwaggerGen; | |
public class OptionSchemaFilter : ISchemaFilter | |
{ | |
public void Apply(OpenApiSchema schema, SchemaFilterContext context) | |
{ | |
if (context.Type.IsGenericType && context.Type.GetGenericTypeDefinition() == typeof(FSharpOption<>)) | |
{ | |
var underlyingType = context.Type.GetGenericArguments()[0]!; | |
if (context.SchemaRepository.TryLookupByType(underlyingType, out var innerSchema)) | |
{ | |
innerSchema.CopyProperties(schema); | |
} | |
else if (underlyingType.IsGenericType && underlyingType.ImplementsInterface(typeof(IEnumerable<>))) | |
{ | |
var paramType = underlyingType.GetGenericArguments()[0]!; | |
if (context.SchemaRepository.TryLookupByType(typeof(IEnumerable<>).MakeGenericType(paramType), out var collSchema)) | |
{ | |
collSchema.CopyProperties(collSchema); | |
} | |
} | |
else | |
{ | |
switch (underlyingType) | |
{ | |
case var str when str == typeof(string): | |
schema.Title = "string"; | |
schema.Type = "string"; | |
break; | |
case var dec when dec == typeof(decimal): | |
schema.Title = "number"; | |
schema.Type = "number"; | |
break; | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Reflection; | |
using LanguageExt; | |
using Microsoft.FSharp.Collections; | |
using Microsoft.FSharp.Core; | |
using Microsoft.FSharp.Reflection; | |
using Microsoft.OpenApi.Models; | |
using Swashbuckle.AspNetCore.SwaggerGen; | |
public class UnionSchemaFilter : ISchemaFilter | |
{ | |
private static readonly Seq<Type> BuiltInTypes = Prelude.Seq( | |
typeof(FSharpOption<>), | |
typeof(FSharpList<>), | |
typeof(FSharpMap<,>) | |
); | |
public void Apply(OpenApiSchema schema, SchemaFilterContext context) | |
{ | |
if ((!context.Type.IsGenericType || !BuiltInTypes.Exists(t => context.Type.GetGenericTypeDefinition() == t)) && FSharpType.IsUnion(context.Type, null)) | |
{ | |
var cases = FSharpType.GetUnionCases(context.Type, null); | |
foreach (var c in cases) | |
{ | |
var caseFields = c.GetFields(); | |
if (caseFields.Length() > 0) | |
{ | |
var caseType = caseFields[0].ReflectedType?.GetTypeInfo().DeclaredFields.FirstOrDefault()?.FieldType; | |
var caseSchema = context.SchemaGenerator.GenerateSchema(caseType, context.SchemaRepository); | |
var wrapped = new OpenApiSchema().Tap(s => s.Properties.Add(c.Name, caseSchema)); | |
schema.OneOf.Add(wrapped); | |
} | |
} | |
} | |
} | |
} |
My bad, forgot GenericExtensions class
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm trying to rewrite your code to F#. But I can't find method CopyProperties from where it goes?