#nullable enable using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Svrnty.CQRS.Configuration; using System; using System.Linq; using System.Reflection; namespace Svrnty.CQRS.MinimalApi; public static class WebApplicationExtensions { /// /// Maps Svrnty CQRS endpoints based on configuration (supports both gRPC and MinimalApi) /// public static WebApplication UseSvrntyCqrs(this WebApplication app) { var config = app.Services.GetService(); // Handle gRPC configuration if available // Note: GrpcCqrsOptions type is from Svrnty.CQRS.Grpc package var grpcOptionsType = Type.GetType("Svrnty.CQRS.Grpc.GrpcCqrsOptions, Svrnty.CQRS.Grpc"); if (grpcOptionsType != null && config != null) { var getConfigMethod = typeof(CqrsConfiguration).GetMethod("GetConfiguration")!.MakeGenericMethod(grpcOptionsType); var grpcOptions = getConfigMethod.Invoke(config, null); if (grpcOptions != null) { // Try to find and call MapGrpcFromConfiguration extension method via reflection // This is generated by the source generator in consumer projects var grpcMethod = FindExtensionMethod("MapGrpcFromConfiguration"); if (grpcMethod != null) { grpcMethod.Invoke(null, new object[] { app }); } else { Console.WriteLine("Warning: MapGrpcFromConfiguration not found. gRPC endpoints were not mapped."); Console.WriteLine("Make sure your project references Svrnty.CQRS.Grpc and has source generators enabled."); } } } // Handle MinimalApi configuration if available var minimalApiOptions = config?.GetConfiguration(); if (minimalApiOptions != null) { if (minimalApiOptions.MapCommands) { app.MapSvrntyCommands(minimalApiOptions.CommandRoutePrefix); } if (minimalApiOptions.MapQueries) { app.MapSvrntyQueries(minimalApiOptions.QueryRoutePrefix); } // TODO: Add dynamic query mapping when available // if (minimalApiOptions.MapDynamicQueries) // { // app.MapSvrntyDynamicQueries(minimalApiOptions.DynamicQueryRoutePrefix); // } } return app; } private static MethodInfo? FindExtensionMethod(string methodName) { // Search through all loaded assemblies for the extension method foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { var types = assembly.GetTypes() .Where(t => t.IsClass && t.IsSealed && !t.IsGenericType && t.IsPublic); foreach (var type in types) { var method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IEndpointRouteBuilder) }, null); if (method != null) return method; } } catch { // Skip assemblies that can't be inspected } } return null; } }