命名服务

百小僧 / 2023-05-19 / 原文

命名服务

 

using System;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class NamedServiceExtensions
    {
        private delegate TService Resolver<out TService>(IServiceProvider serviceProvider, string serviceName);

        public static TService GetNamedService<TService>(
            this IServiceProvider provider, string serviceName)
        {
            return ((Resolver<TService>)provider
                    .GetService(typeof(Resolver<TService>)))
                ?.Invoke(provider, serviceName);
        }

        public static IServiceCollection AddNamedTransient<TService, TImplementation>(
            this IServiceCollection services, string name) where TService : class where TImplementation : class, TService
        {
            services.AddTransient<TService, TImplementation>();
            services.AddTransient(provider =>
                (Resolver<TService>)((sp, sn) => sn == name ? sp.GetService<TService>() : null));
            return services;
        }

        public static IServiceCollection AddNamedScoped<TService, TImplementation>(
            this IServiceCollection services, string name) where TService : class where TImplementation : class, TService
        {
            services.AddScoped<TService, TImplementation>();
            services.AddTransient(provider =>
                (Resolver<TService>)((sp, sn) => sn == name ? sp.GetService<TService>() : null));
            return services;
        }

        public static IServiceCollection AddNamedSingleton<TService, TImplementation>(
            this IServiceCollection services, string name) where TService : class where TImplementation : class, TService
        {
            services.AddSingleton<TService, TImplementation>();
            services.AddTransient(provider =>
                (Resolver<TService>)((sp, sn) => sn == name ? sp.GetService<TService>() : null));
            return services;
        }
    }
}

var services = new ServiceCollection();

services.AddNamedTransient<IMyService, MyService>("serviceA");
services.AddNamedScoped<IMyService, MyOtherService>("serviceB");
services.AddNamedSingleton<IMyService, MyThirdService>("serviceC");

var serviceProvider = services.BuildServiceProvider();

var serviceA = serviceProvider.GetNamedService<IMyService>("serviceA");
var serviceB = serviceProvider.GetNamedService<IMyService>("serviceB");
var serviceC = serviceProvider.GetNamedService<IMyService>("serviceC");