2012-05-04 103 views
8

我正在使用Ninject框架構建MVC3應用程序。我有一個耗時的初始化服務,最後這個服務將有一個包含用戶特定信息的對象,那麼只要用戶會話處於活動狀態,我就需要重新使用該服務,以便我可避免再次初始化服務,並再次MVin3中的Ninject會話範圍概念

所以我的問題是

當我綁定使用Ninject我應該選擇什麼樣的範圍內的服務,有在Ninject每範圍沒有會話,那麼什麼是最好的實施要求的方式?還是我根本走錯了方向?

我創建了一個自定義提供爲我服務,這將創建一個基於從當前Controller.User.Identity.Name抓住用戶名信息的服務之一。下面的代碼將不起作用,因爲userName的局部變量是缺少的,我怎麼能通過Ninject將用戶名值傳遞給我的自定義提供程序,以便我可以從IContext中提取它?

public class TfsConnectionManagerProvider : Provider<TfsConnectionManager> 
    { 
     protected override TfsConnectionManager CreateInstance(IContext context) 
     { 
      Uri serverUri = new Uri(ConfigurationHelper.TfsServerUrl); 
      // Connect to the server without impersonation 
      using (TfsTeamProjectCollection baseUserConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri)) 
      { 
       // Get the identity management service 
       IIdentityManagementService ims = baseUserConnection.GetService<IIdentityManagementService>(); 

       // Get the identity to impersonate 
       TeamFoundationIdentity identity = ims.ReadIdentity 
       (
        IdentitySearchFactor.AccountName, 
        userName, //NOTE: How can I get user name value from IContext??? 
        MembershipQuery.None, 
        ReadIdentityOptions.None 
       ); 

       // Connect using the impersonated identity 
       using (TfsTeamProjectCollection impersonatedConnection = new TfsTeamProjectCollection(serverUri, identity.Descriptor)) 
       { 
        WorkItemStore store = impersonatedConnection.GetService<WorkItemStore>(); 

        return new TfsConnectionManager 
        { 
         Store = store 
        }; 
       } 
      } 
     } 
    } 
+0

也參看:http完成。com/questions/4687707/ninject-per-session-singleton –

回答

2

我變成使用自定義提供用於創建實例,並在自定義提供我檢查,如果它存在於會話與否。 //計算器:

綁定是如下

Bind<IRepository>().ToProvider(new TfsRepositoryProvider()); 

自定義提供低於

public class TfsRepositoryProvider : Provider<TfsRepository> 
    { 
     private const string SesTfsRepository = "SES_TFS_REPOSITORY"; 

     protected override TfsRepository CreateInstance(IContext context) 
     { 
      // Retrieve services from kernel 
      HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>(); 

      if (httpContext == null || httpContext.Session == null) 
      { 
       throw new Exception("No bind service found in Kernel for HttpContextBase"); 
      } 

      return (httpContext.Session[SesTfsRepository] ?? (
        httpContext.Session[SesTfsRepository] = new TfsRepository(context.Kernel.Get<IWorkItemStoreWrapper>())) 
       ) as TfsRepository; 
     } 
    } 
0

好的,您可以在應用程序中緩存/存儲用戶信息,並且只在您沒有(最近)用戶信息時調用外部服務。在你的用戶信息檢索「圖層」中,你只需編程這兩種可能性。

你在哪裏緩存,它完全取決於你自己。您可以將此信息存儲在本地數據庫中。

顯然,我明白你錯了,我道歉(下面我原來的答覆)。

例如,您可以使用一個(抽象)工廠,該工廠包含服務的靜態 成員(例如),以便它將被重用。

雖然這取決於你的服務,這可能有一些不必要的副作用 效果(我沒有這一次與數據服務,並在ASP.NET MVC3 應用我的數據方面,由於一些魔法 事是有點擰緊)。我想說的是:小心並且測試它 好。

+0

抱歉,我可能無法很好地解釋我的問題,服務的初始化包括調用某些Web服務,然後返回用戶特定的信息。我無法使它成爲靜態的,因爲它是用戶特定的 – Ming

+0

噢,然後我誤解了你:)。你可以做的就是嘗試緩存你的應用程序中的用戶數據(信息),並且只在你自己沒有用戶信息時才調用外部服務。 – Styxxy

+0

是的,所以說到我上面的真實問題 - 我如何通過Ninject綁定使用範圍 – Ming

7

會話範圍有意不在Ninject中提供,因爲會話狀態中的服務在幾乎所有情況下都是錯誤的。你應該非常小心地使用會話狀態,因爲它帶來很多缺點。

嘗試在首位無狀態的應用程序。

如果在會話範圍內有數據的充分理由,那麼將該數據(而不是服務)放入會話狀態,並使用單點,瞬態或請求範圍內的服務進行處理(數據和功能的分離)。

+0

謝謝Remo,可能會讓我感到困惑,因爲我把會話放在了我的原始描述中。我並不是說我要使用會話來保存數據,其目標是儘可能使用Ninject框架重新使用從長時間運行的服務返回的用戶特定對象。任何適當的設計理念都會受到歡迎 – Ming