using Microsoft.Extensions.DependencyInjection; namespace LanMountainDesktop.Shared.IPC.DependencyInjection; public static class ServiceCollectionExtensions { public static IServiceCollection AddLanMountainDesktopIpcHost( this IServiceCollection services, string? pipeName = null) { ArgumentNullException.ThrowIfNull(services); services.AddSingleton(provider => { var host = new PublicIpcHostService(pipeName ?? IpcConstants.DefaultPipeName); foreach (var registration in provider.GetServices()) { var implementation = registration.ImplementationFactory(provider); host.RegisterPublicService( registration.ContractType, implementation, registration.ObjectId, registration.PluginId, registration.NotifyIds); } host.Start(); return host; }); services.AddSingleton(provider => provider.GetRequiredService()); return services; } public static IServiceCollection AddPublicIpcService( this IServiceCollection services, string? objectId = null, string? pluginId = null, params string[] notifyIds) where TContract : class where TImplementation : class, TContract { ArgumentNullException.ThrowIfNull(services); EnsureSingletonRegistration(services); if (!services.Any(descriptor => descriptor.ServiceType == typeof(PublicIpcServiceRegistration) && descriptor.ImplementationInstance is PublicIpcServiceRegistration existing && existing.ContractType == typeof(TContract) && string.Equals(existing.ObjectId, objectId, StringComparison.Ordinal))) { services.AddSingleton(new PublicIpcServiceRegistration( typeof(TContract), provider => provider.GetRequiredService(), objectId, pluginId, notifyIds ?? [])); } return services; } private static void EnsureSingletonRegistration(IServiceCollection services) where TContract : class where TImplementation : class, TContract { var descriptor = services.LastOrDefault(item => item.ServiceType == typeof(TContract)); if (descriptor is null) { services.AddSingleton(); return; } if (descriptor.Lifetime != ServiceLifetime.Singleton) { throw new InvalidOperationException( $"Public IPC contract '{typeof(TContract).FullName}' must be registered as Singleton."); } } }