2

我已經在MVC3應用程序中成功實現了Ninject,但是在使用ASP.NET Web窗體執行同樣的操作時遇到了一些麻煩。每次嘗試訪問業務層中的注入屬性時,我都會收到空引用。在CreateKernel方法中設置斷點以及ServiceLocator類中的幾個位置之後,看起來它們都沒有被擊中,所以它甚至沒有被加載。Ninject + ASP.NET Web窗體無法正常工作

我敢肯定,我只是接近這個錯誤,但是很少有文檔或信息用於在Web窗體應用程序中連接Ninject。

基本上這裏是我到目前爲止有:

代碼背後

public class ReviewManager 
    { 
     [Inject] private IReviewRepository _reviewRepository { get; set; } 

     public ReviewManager() { } 

     public ReviewManager(IReviewRepository reviewRepository) 
     { 
      _reviewRepository = reviewRepository; 
     } 

     public Review GetById(int id) 
     { 
      if (id <= 0) throw new ArgumentException("ID must be greater than zero"); 

      **I get a null reference exception on the next line. _reviewRepository is null** 
      return _reviewRepository.GetById(id); 
     } 
} 

的global.asax.cs

public class Global : NinjectHttpApplication 
{ 
    protected override IKernel CreateKernel() 
    { 
     return ServiceLocator.Kernel; 
    } 

    // deleted for brevity 
} 

ServiceLocator.cs(編輯爲簡潔,相關部分在這裏)

​​
+0

這裏的關鍵問題是:誰的實例化ReviewManager? – Jeff

+0

它從任何ASP.NET代碼隱藏實例化。 – Scott

+0

使用您的ServiceLocator或通過創建新的ReviewManager? – Jeff

回答

1

ASP.Net通過WebForms不允許您管理所有對象實例的生命週期(如MVC)。例如,框架實例化頁面對象。這意味着你可能無法像在MVC/WPF/Silverlight中一樣執行DI(WinForms IIRC中存在同樣的問題)。您可能必須直接在每個代碼後面啓動依賴關係圖。

翻譯:當您的頁面加載時(或者在屬性上使用lazy-init),您將需要調用ServiceLocator.Kernel.Get<IReviewRepository>

+0

謝謝,這確實有效。我已經看到一些關於如何模擬與MVC相同類型的生命週期管理的文章,所以我打算保持這個線程開放,但如果在幾天內沒有其他解決方案提出這種說法,我會將此標記爲答案。 – Scott

2

關於MVC的一件很酷的事情是,它可以在同一個應用程序中運行ASP.NET WebForm頁面。在我看來,擴展ASP.NET WebForms網站的最佳方式是使用MVC3創建新頁面,並重構每個需要對MVC3進行重大更改的頁面。

如果這不是選項,請使用Ninject.Web擴展。它包含一個IHttpModule,它在初始化後會注入所有網頁和控件。通過這種方式,您可以將資源注入Ninject創建的服務。

+0

我完全同意MVC是更好的選擇,但我試圖向現有的Web表單應用程序介紹一些體系結構更改。我會看看Ninject.Web。 – Scott

0

潛在的解決方法,通過改變你的數據綁定類,如下所示:

public class DataBindings : NinjectModule 
    { 
     public override void Load() 
     { 
      Bind<IReviewRepository>().To<ReviewRepository>(); 
      Bind<ReviewManager>().ToSelf(); 
     } 
    } 

而你的範圍內,主叫,而不是

var rm = new ReviewManager(); 

使用

var rm = ServiceLocator.Kernel.Get<ReviewManager>(); 

我還沒有測試這種嘗試代碼,但我認爲它會解決你的空引用問題。

0

我使用屬性注入的頁面,masterpages和usercontrols。我所有的頁面,例如,從覆蓋RequestActivation方法用下面的代碼基類繼承:

''' <summary> 
    ''' Asks the kernel to inject this instance. 
    ''' </summary> 
    Protected Overridable Sub RequestActivation() 
     ServiceLocator.Kernel.Inject(Me) 
    End Sub 

而且在每一頁我宣佈注射性質:

<Inject()> 
    Property repo As IMyRepository