From 0e56969bfb2537d4ca89810fde1ae75b9c494aca Mon Sep 17 00:00:00 2001 From: Jacob Marks Date: Wed, 24 Apr 2024 20:24:29 +1000 Subject: [PATCH] Use source generator --- .../RequestDelegateSourceGenerator.cs | 36 +++++++++++++++++++ .../Server.Core.SourceGenerators.csproj | 19 ++++++++++ Server.Core/QueryBindingEvaluator.cs | 9 ++--- Server.Core/Server.Core.csproj | 4 +++ dotnet-qs.sln | 6 ++++ 5 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 Server.Core.SourceGenerators/RequestDelegateSourceGenerator.cs create mode 100644 Server.Core.SourceGenerators/Server.Core.SourceGenerators.csproj diff --git a/Server.Core.SourceGenerators/RequestDelegateSourceGenerator.cs b/Server.Core.SourceGenerators/RequestDelegateSourceGenerator.cs new file mode 100644 index 0000000..1f417f5 --- /dev/null +++ b/Server.Core.SourceGenerators/RequestDelegateSourceGenerator.cs @@ -0,0 +1,36 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Microsoft.CodeAnalysis; + +namespace Server.Core.SourceGenerators; + +[Generator(LanguageNames.CSharp)] +public class RequestDelegateSourceGenerator : ISourceGenerator +{ + public void Initialize(GeneratorInitializationContext context) + { + } + + public void Execute(GeneratorExecutionContext context) + { + static string indent(int depth = 1) => new(' ', 4 * depth); + + context.AddSource($"Generated.RequestDelegates.g.cs", + $$""" + // + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + + namespace {{context.Compilation.AssemblyName}}; + + public static partial class Generated + { + public static (string Route, Delegate Delegate)[] RequestDelegates = + [ + {{string.Join("\n" + indent(2), Shared.Constants.Endpoints.Select(e => + $"(\"{e.Route}\", ([FromQuery] {e.Type} q, HttpResponse r) => r.WriteAsJsonAsync(q)),"))}} + ]; + } + """); + } +} diff --git a/Server.Core.SourceGenerators/Server.Core.SourceGenerators.csproj b/Server.Core.SourceGenerators/Server.Core.SourceGenerators.csproj new file mode 100644 index 0000000..87f3aeb --- /dev/null +++ b/Server.Core.SourceGenerators/Server.Core.SourceGenerators.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + \ No newline at end of file diff --git a/Server.Core/QueryBindingEvaluator.cs b/Server.Core/QueryBindingEvaluator.cs index 1108636..f2fff72 100644 --- a/Server.Core/QueryBindingEvaluator.cs +++ b/Server.Core/QueryBindingEvaluator.cs @@ -13,11 +13,6 @@ namespace Server.Core; public class QueryBindingEvaluator : IDisposable { - private static Delegate CreateEndpointDelegate() => ([FromQuery] T q, HttpResponse r) => r.WriteAsJsonAsync(q); - private static readonly MethodInfo createEndpointDelegateMethod = typeof(QueryBindingEvaluator) - .GetMethod(nameof(CreateEndpointDelegate), 1, BindingFlags.NonPublic | BindingFlags.Static, null, [], null) - ?? throw new InvalidOperationException($"Could not find {nameof(CreateEndpointDelegate)} method."); - private readonly TestServer _minimalApiTestServer; private readonly HttpClient _minimalApiTestServerClient; @@ -46,8 +41,8 @@ private static TestServer CreateMinimalApiTestServer() app.UseRouting(); app.UseEndpoints(endpoints => { - foreach (var endpoint in Constants.Endpoints) - endpoints.MapGet(endpoint.Route, (Delegate)createEndpointDelegateMethod.MakeGenericMethod(endpoint.ParamType).Invoke(null, null)!); + foreach (var (route, @delegate) in Generated.RequestDelegates) + endpoints.MapGet(route, @delegate); }); }); diff --git a/Server.Core/Server.Core.csproj b/Server.Core/Server.Core.csproj index dcf27e4..ac5b127 100644 --- a/Server.Core/Server.Core.csproj +++ b/Server.Core/Server.Core.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true @@ -16,6 +17,9 @@ + \ No newline at end of file diff --git a/dotnet-qs.sln b/dotnet-qs.sln index 90e8481..f1fbc57 100644 --- a/dotnet-qs.sln +++ b/dotnet-qs.sln @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "Shared\Shared.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server.Core.Tests", "Server.Core.Tests\Server.Core.Tests.csproj", "{5A856409-9FA3-4C23-B65B-3BCA7275EBC1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server.Core.SourceGenerators", "Server.Core.SourceGenerators\Server.Core.SourceGenerators.csproj", "{2B7D08BF-781C-421B-9C9A-E5B03F606A1A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,5 +44,9 @@ Global {5A856409-9FA3-4C23-B65B-3BCA7275EBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A856409-9FA3-4C23-B65B-3BCA7275EBC1}.Release|Any CPU.ActiveCfg = Release|Any CPU {5A856409-9FA3-4C23-B65B-3BCA7275EBC1}.Release|Any CPU.Build.0 = Release|Any CPU + {2B7D08BF-781C-421B-9C9A-E5B03F606A1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B7D08BF-781C-421B-9C9A-E5B03F606A1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B7D08BF-781C-421B-9C9A-E5B03F606A1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B7D08BF-781C-421B-9C9A-E5B03F606A1A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal