public static IServiceCollection AddKeyedServiceManager(this IServiceCollection services,
                                                                out IKeyedServiceManager manager)
        {
            manager = new KeyedServiceManager();

            return(services.AddSingleton(manager));
        }
        public static IServiceCollection SetKeyed <ServiceType, ImplType>(this IServiceCollection services,
                                                                          IKeyedServiceManager manager, object key, Func <IServiceProvider, ImplType> factory = null,
                                                                          ServiceLifetime lifetime = ServiceLifetime.Scoped) where ImplType : ServiceType
        {
            Func <IServiceProvider, object> finalFactory = null;

            if (factory != null)
            {
                finalFactory = (provider) => factory(provider);
            }

            return(services.SetKeyed(manager, typeof(ServiceType), typeof(ImplType), key, finalFactory, lifetime));
        }
        public static IServiceCollection SetKeyed(this IServiceCollection services,
                                                  IKeyedServiceManager manager,
                                                  Type serviceType, Type implType, object key, Func <IServiceProvider, object> factory = null,
                                                  ServiceLifetime lifetime = ServiceLifetime.Scoped)
        {
            if (!serviceType.IsAssignableFrom(implType))
            {
                throw new InvalidOperationException("ServiceType is not assignable from ImplType");
            }

            var keyedType = typeof(KeyedService <>).MakeGenericType(implType);

            if (!manager.ServiceTypes.ContainsKey(serviceType))
            {
                manager.ServiceTypes[serviceType] = new KeyedServiceInfo
                {
                    CachedObjectFactory = new Dictionary <Type, ObjectFactory>(),
                    ServiceLifetime     = lifetime,
                    Types = new Dictionary <object, (Type, Type, Func <IServiceProvider, object>)>()
                }
            }
            ;

            var info = manager.ServiceTypes[serviceType];

            info.Types[key] = (keyedType, implType, factory);
            info.CachedObjectFactory[implType] = ActivatorUtilities.CreateFactory(implType, new Type[] { });

            switch (lifetime)
            {
            case ServiceLifetime.Scoped:
                services.AddScoped(keyedType);
                break;

            case ServiceLifetime.Transient:
                services.AddTransient(keyedType);
                break;

            case ServiceLifetime.Singleton:
                services.AddSingleton(keyedType);
                break;
            }

            return(services);
        }