Skip to content

Instantly share code, notes, and snippets.

@Cologler
Created June 25, 2024 09:47
Show Gist options
  • Save Cologler/9a5a88f7cf758ec06085427e2e7c18db to your computer and use it in GitHub Desktop.
Save Cologler/9a5a88f7cf758ec06085427e2e7c18db to your computer and use it in GitHub Desktop.
Singleton helper for DI
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
public interface ISingletonService<out TService>
{
TService Serivce { get; }
}
public static class SingletonServiceHelper
{
/// <summary>
/// Allows to resolve <see cref="ISingletonService{}"/> from the <see cref="IServiceProvider"/>.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection UseSingletonService(this IServiceCollection services)
{
ThrowIfNull(services);
services.TryAddSingleton(typeof(ISingletonService<>), typeof(SingletonService<>));
return services;
}
sealed class SingletonService<T>(T serivce) : ISingletonService<T>
{
public T Serivce { get; } = serivce;
}
/// <summary>
/// Use <see cref="ISingletonService{}"/> to get the root <see cref="IServiceProvider"/>.
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
public static IServiceProvider GetRootServiceProvider(this IServiceProvider serviceProvider)
{
ThrowIfNull(serviceProvider);
return serviceProvider.GetRequiredService<ISingletonService<IServiceProvider>>().Serivce;
}
public static bool IsRootServiceProvider(this IServiceProvider serviceProvider)
{
ThrowIfNull(serviceProvider);
return ReferenceEquals(
serviceProvider,
serviceProvider.GetRequiredService<ISingletonService<IServiceProvider>>().Serivce);
}
/// <summary>
/// Ensure the <paramref name="serviceProvider"/> is a scoped <see cref="IServiceProvider"/>.
/// </summary>
/// <param name="serviceProvider"></param>
/// <exception cref="InvalidOperationException"></exception>
public static void CheckScoped(this IServiceProvider serviceProvider)
{
if (serviceProvider.IsRootServiceProvider())
throw new InvalidOperationException();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment