// Create scope dependency
        public object BindPerScope(IContext context)
        {
            var key = context.Request.Service;

            MicrodotNinjectScopeParameter scope =
                context.Parameters
                .OfType <MicrodotNinjectScopeParameter>()
                .LastOrDefault();

            if (scope != null)
            {
                //Handle the lock inside in the cache item scope
                return(scope.GetORCreate(key, () => context.Kernel.Get(key, ResolveRealParameter.instance)));
            }

            // Can occur if resolve by Ikeranl/ Fun<T>/ IResoltionRoot
            // Scope only transfer from the serviceProvider
            throw new GlobalScopeNotSupportFromNinject($"{key.FullName}");
        }
 public MicrodotServiceProviderWithScope(IResolutionRoot resolver)
 {
     _cacheItem = new ScopeCache();
     _microdotNinectScopParameter = new MicrodotNinjectScopeParameter(_cacheItem, this);
     _resolver = resolver;
 }
        public void ConfigureServices(IServiceCollection services)
        {
            DeadlockDetector.validate(services);
            foreach (var descriptor in services)
            {
                IBindingWhenInNamedWithOrOnSyntax <object> binding;

                if (descriptor.ImplementationType != null)
                {
                    binding = Kernel.Bind(descriptor.ServiceType).To(descriptor.ImplementationType);
                }

                else if (descriptor.ImplementationFactory != null)
                {
                    binding = Kernel.Bind(descriptor.ServiceType).ToMethod(context =>
                    {
                        var serviceProvider = context.Kernel.Get <IServiceProvider>();
                        return(descriptor.ImplementationFactory(serviceProvider));
                    });
                }
                else
                {
                    binding = Kernel.Bind(descriptor.ServiceType).ToConstant(descriptor.ImplementationInstance);
                }

                switch (descriptor.Lifetime)
                {
                case ServiceLifetime.Singleton:
                    binding.InSingletonScope();
                    break;

                case ServiceLifetime.Scoped:

                    // Determent when to return the real instance
                    binding.When((r) => r.Parameters.Contains(ResolveRealParameter.instance));

                    // Return instance from scope cache or use the realBinding to create it
                    Kernel.Bind(descriptor.ServiceType)
                    .ToMethod(BindPerScope).InTransientScope();
                    break;

                case ServiceLifetime.Transient:
                    binding.InTransientScope();
                    break;
                }
            }

            // note !! every thing that cache, ServiceProvider should be Transient to enable scope inheritance
            Kernel.Rebind(typeof(IKeyedServiceCollection <,>)).To(typeof(KeyedServiceCollection <,>)).InTransientScope();
            Kernel.Rebind(typeof(ILoggerFactory)).To(typeof(NonBlockingLoggerFactory)).InSingletonScope();
            Kernel.Bind <IServiceScopeFactory>().To <MicrodotServiceScopeFactory>().InSingletonScope();

            // Support unique scoping created by the IServiceScopeFactory
            Kernel.Bind <MicrodotServiceProviderWithScope>().ToSelf().InTransientScope();

            //Support Global scoping
            Kernel.Bind <IGlobalServiceProvider>().To <MicrodotServiceProviderWithScope>().InSingletonScope();

            //Support inherit scope and global scoping
            Kernel.Bind <IServiceProvider>().ToMethod(context =>
            {
                MicrodotNinjectScopeParameter scope =
                    context.Parameters
                    .OfType <MicrodotNinjectScopeParameter>()
                    .LastOrDefault();
                bool hasScope = (scope != null);
                if (hasScope)
                {
                    return(scope.ServiceProvider);
                }

                return(context.Kernel.Get <IGlobalServiceProvider>());
            }).InTransientScope();
        }