Ninject InSingletonScope with Web Api RC

后端 未结 3 749
野性不改
野性不改 2020-12-05 03:02

I\'m having some difficulty using Ninject\'s InSingletonScope binding with Web Api RC. No matter how I create my binding, it looks like perhaps Web Api is handling scope/li

相关标签:
3条回答
  • 2020-12-05 03:56

    @Remo Gloor When I run your code in InMemoryHost of WebAPI and run Integration tests everything works fine and I do have singleton. If I run WebAPI solution inside VS Cassini web server first run is successful and when I click refresh I receive exception : Error loading Ninject component ICache No such component has been registered in the kernel's component container.

    If I return old code with BeginBlock it works in Cassini but IsSingleton not working anymore in integration tests.

    0 讨论(0)
  • use

    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel);
    }
    

    and don't dispose the kernel in the NinjectDependencyScope

    0 讨论(0)
  • 2020-12-05 04:02

    Instead of not disposing the kernel (which will not call the internal dispose) you can simply implement your own singleton:

    public static class NinjectSingletonExtension
    {
        public static CustomSingletonKernelModel<T> SingletonBind<T>(this IKernel i_KernelInstance)
        {
            return new CustomSingletonKernelModel<T>(i_KernelInstance);
        }
    }
    
    public class CustomSingletonKernelModel<T>
    {
        private const string k_ConstantInjectionName = "Implementation";
        private readonly IKernel _kernel;
        private T _concreteInstance;
    
    
        public CustomSingletonKernelModel(IKernel i_KernelInstance)
        {
            this._kernel = i_KernelInstance;
        }
    
        public IBindingInNamedWithOrOnSyntax<T> To<TImplement>(TImplement i_Constant = null) where TImplement : class, T
        {
            _kernel.Bind<T>().To<TImplement>().Named(k_ConstantInjectionName);
            var toReturn =
                _kernel.Bind<T>().ToMethod(x =>
                                           {
                                               if (i_Constant != null)
                                               {
                                                   return i_Constant;
                                               }
    
                                               if (_concreteInstance == null)
                                               {
                                                   _concreteInstance = _kernel.Get<T>(k_ConstantInjectionName);
                                               }
    
                                               return _concreteInstance;
                                           }).When(x => true);
    
            return toReturn;
        }
    }
    

    And then simply use:

    i_Kernel.SingletonBind<T>().To<TImplement>();
    

    Rather then

    i_Kernel.Bind<T>().To<TImplement>().InSingletonScope();
    


    note: although it is only matters for the first request, this implementation is not thread safe.

    0 讨论(0)
提交回复
热议问题