Accessing the Ninject Kernel Globally

后端 未结 4 452
名媛妹妹
名媛妹妹 2021-02-05 09:25

This question is not specifically related to Ninject. It\'s more of a general coding question, but I\'m posting it here in case there might be a better way entirely of handling

相关标签:
4条回答
  • 2021-02-05 09:57

    I managed to get the Service Locator working, and it appears to be working quite well. When a request enters the application through an MVC Controller Action Method, Ninject functions in the normal way provided by Ninject.Mvc.Extensions. It injects instance classes through the controller constructor. When a request enters the application in any other way, I call the Service Locator to supply the instance classes in that classes constructor.

    Here's the code:

    First, a reference to Microsoft.Practices.ServiceLocation

    And the following Ninject adapter class.

    public class NinjectServiceLocator : ServiceLocatorImplBase
    {
        public IKernel Kernel { get; private set; }
    
        public NinjectServiceLocator(IKernel kernel)
        {
            Kernel = kernel;
        }
    
        protected override object DoGetInstance(Type serviceType, string key)
        {
            return Kernel.Get(serviceType, key);
        }
    
        protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
        {
            return Kernel.GetAll(serviceType);
        }
    }
    

    And in Global.asax

    public class MvcApplication : NinjectHttpApplication
    {
        private static IKernel _kernel;
    
    
        protected override IKernel CreateKernel()
        {
            return Container;
        }
    
        private static IKernel Container
        {
            get
            {
                if (_kernel == null)
                {
                    _kernel = new StandardKernel();
                    _kernel.Load(new ServiceModule(), new RepositoryModule());
    
                    ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(_kernel));
                }
    
                return _kernel;
            }
        }
    }
    

    Note this code requires the use of Ninject.Mvc.Extensions, which provides dependency resolver fallback to the default controller. Otherwise, a custom dependency resolver may be required.

    This appears to resolve all my concerns. It creates the instance classes, resolves the entire object graph, and works from anywhere I need it to work. And, as far as I can tell, there is only one Ninject Standard Kernel per application.

    I know using the Service Locator pattern is frowned upon, but I imagine using more than one Ninject kernel would be frowned upon even worse.

    Fred Chateau

    0 讨论(0)
  • 2021-02-05 09:58

    Newer version of Ninject has this method if used with System.Web.MVC:

    var obj = DependencyResolver.Current.GetService<IClassName>();
    

    Unless you need to manipulate DI bindings on the fly, but instantiating a StandardKernel is a little heavy.

    IKernel kernel = new StandardKernel();
    var obj = DependencyResolver.Current.GetService<IClassName>();
    
    0 讨论(0)
  • 2021-02-05 10:04

    The most simple way (IMO):

    _className = (IClassName)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IClassName));
    
    0 讨论(0)
  • 2021-02-05 10:23

    It sounds like you're needing more of a Factory pattern implementation of Ninject. You could migrate the Kernel from the Global.asax to a Factory class which could be interacted with by the rest of your application.

    Alternatively if you have a situation where a parameter specified at runtime is to determine the interface bindings you could wrap the service. This is a hybrid setup of DI and ServiceLocater, but the ServiceLocater only occurs at service level instantiation, all other layers are coded normally in a DI/IOC pattern.

    MyService : IService1
    {
        public void DoSomething(MyCustomParameter parameter)
        {
            //Builds the Kernel using the supplied parameter
            //We've in our resolver bound IService1 To MyActualService
            var trueService = kernel.Get<IService1>();
            return trueService.DoSomething(parameter);
        }
    }
    
    MyActualService : IService1
    {
        public void DoSomething()
        {
            //Do the Actual work
        }
    }
    
    0 讨论(0)
提交回复
热议问题