2013-03-11 71 views
11

這個問題是不是特別相關,Ninject。它更像是一個普通的編碼問題,但我在這裏張貼的情況下有可能完全處理在Ninject的問題,比什麼,我試圖做一個更好的辦法。訪問Ninject內核全局

我想知道是否有可能在全球範圍內訪問Ninject標準內核,其在Global.asax中的實例。

下面是代碼:

public class MvcApplication : NinjectHttpApplication 
{ 
    protected override void OnApplicationStarted() 
    { 
     base.OnApplicationStarted(); 

     // MVC global registration, routing and filtering code goes here... 
    } 

    protected override IKernel CreateKernel() 
    { 
     return Container; 
    } 

    private static IKernel Container 
    { 
     get 
     { 
      IKernel kernel = new StandardKernel(); 
      kernel.Load(new ServiceModule(), new RepositoryModule()); 
      return kernel; 
     } 
    } 
} 

如果我有一些類,例如,不與控制器,在這裏我想開始一個依賴鏈接口門面類,我的理解是,我應該用途:

_className = kernel.Get<IClassName>(); 

但是,我知道要做到這一點的唯一方法是創建Ninject標準內核的新實例,但如果我理解正確的話,是不是要創建一個新的實例是個好主意Ninject內核,因爲那基本上是創建第二個ke rnel。

那麼,是不是可以訪問現有的內核是在Global.asax中在應用程序啓動實例,從任何地方在我的應用程序,或者是完全有更好的方法來做到這一點?

問候,

弗雷德酒莊

回答

0

這聽起來像你需要更多的Ninject的工廠模式實現的。您可以將內核從Global.asax遷移到Factory類,該類可以與您的應用程序的其餘部分進行交互。

另外,如果你遇到這樣的情況在運行時指定的參數是要確定接口綁定,你可以換服務。這是DI和ServiceLocater的混合設置,但ServiceLocater僅發生在服務級別的實例化,所有其他層以DI/IOC圖案正常編碼。

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 
    } 
} 
+1

你碰巧知道如何爲工廠設置會影響MVC擴展實現? – 2013-03-12 03:38:32

+0

可悲的是這部分我不知道沒有嘗試它。由於獨特的關注點和架構選擇,我使用上面列出的包裝方法來處理正在處理的應用程序。 – Kaiser12 2013-03-12 11:24:15

1

我設法讓服務定位器工作,它似乎工作得很好。當請求通過MVC控制器操作方法進入應用程序時,Ninject以Ninject.Mvc.Extensions提供的正常方式運行。它通過控制器構造函數注入實例類。當請求以任何其他方式進入應用程序時,我調用服務定位器來爲該類構造函數提供實例類。

下面的代碼:

一是Microsoft.Practices.ServiceLocation

參考

而下面Ninject適配器類。

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); 
    } 
} 

而且在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; 
     } 
    } 
} 

注意此代碼需要使用Ninject.Mvc.Extensions的,它提供了依賴解析器回退到默認的控制器。否則,可能需要自定義依賴項解析器。

這似乎解決了我所有的問題。它創建實例類,解析整個對象圖,並在我需要的任何地方工作。而且,據我所知,每個應用程序只有一個Ninject標準內核。

我知道使用Service Locator模式是不可取的,但我想使用一個以上的Ninject內核會在更糟地皺起了眉頭。

弗雷德酒莊

20

最簡單的方法(IMO):如果使用System.Web.MVC

_className = (IClassName)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(IClassName)); 
2

更新的版本Ninject有這個方法:

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

除非你需要操縱的飛行DI綁定,但實例化一個StandardKernel是有點重。

IKernel kernel = new StandardKernel(); var obj = DependencyResolver.Current.GetService<IClassName>();