using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using Grpc.Net.Client; using MagicOnion.Client; using System; using System.Linq; using System.Threading.Tasks; namespace DysonNetwork.Shared.Etcd { public static class EtcdServiceExtensions { public static IServiceCollection AddEtcdService(this IServiceCollection services, IConfiguration configuration) { var etcdConnectionString = configuration.GetConnectionString("Etcd"); services.AddSingleton(new EtcdService(etcdConnectionString!)); return services; } public static IServiceCollection AddMagicOnionService(this IServiceCollection services) where TService : class, MagicOnion.IService { services.AddSingleton(serviceProvider => { var etcdService = serviceProvider.GetRequiredService(); var serviceName = typeof(TService).Name.TrimStart('I'); // Convention: IMyService -> MyService // Synchronously wait for service discovery (or handle asynchronously if preferred) var endpoints = etcdService.DiscoverServicesAsync(serviceName).GetAwaiter().GetResult(); if (!endpoints.Any()) { throw new InvalidOperationException($"No endpoints found for MagicOnion service: {serviceName}"); } // For simplicity, use the first discovered endpoint var endpoint = endpoints.First(); var channel = GrpcChannel.ForAddress(endpoint); return MagicOnionClient.Create(channel); }); return services; } } }