2017-08-09 25 views
0

我很努力地實現一個功能來爲Ninject IoC啓用自定義會話範圍。我的要求是,對於唯一的會話id(int),我會得到綁定到特定接口的對象的新實例。 第二個要求是它必須可以在Get被調用的地方。如何將會話ID傳遞給Ninject容器以獲取會話綁定的對象實例?

問題是,IKernel.Get <>無法傳遞會話ID。我不能使用.InScope(),因爲靜態實例將無法訪問當前會話ID。 (可以使用無Session.Current模式)。

會話只能通過唯一的整數進行區分,並且可以同時運行多個會話。

除了每次創建一個單獨的容器之外,還有什麼想法?恐怕它可能是昂貴的。複製容器? Ninject有可能嗎?

謝謝,Radek

+1

防止讓對象圖的構造依賴於運行時數據。閱讀[this](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99)以獲取更多信息。 – Steven

回答

1

你的假設是錯誤的。

  • InScope不需要靜態字段。方法簽名是InScope(Func<IContext, object> scope)。所以你有權訪問IContext - 這不是靜態的。
  • Get重載接受IParameter s。這些放在IContext。您可以爲會話範圍創建自定義IParameter實現。所以有一種方法可以將您的會話傳遞給Get

但是,只有一個整數作爲會話ID可能無法正常工作。由於範圍對象需要是引用類型,而不是值類型,因此需要涉及拳擊。 Ninject可能無法正確支持這一點 - 以防比較引用而不是整數值。此外,清理(IDisposable.Dispose()調用)可能會提前完成。 Ninject保持對範圍的弱引用。如果範圍對象不執行INotifyWhenDisposed它定期檢查弱引用是否已經死亡。當它死了,它會做資源清理。當然,如果ninject獲得自己的「盒子」對象並且只保留一個弱引用,GC可以隨時收集這個對象。意味着你的資源可以在範圍實際結束之前處理。

所以你需要將你的scope-id包裝在一個對象中(並且保留對這個對象的引用,而不僅僅是該值),並且最好使它實現INotifyWhenDisposed以進行確定性資源清理。


提示:也許InCallScope - 包含在Ninject.Extensions.NamedScope將是你的使用情況更適合。

另一種可能的選擇是每個會話採用ChildKernel。這與每個會話創建一個內核類似 - 但它不是重量級的。

+0

「靜態字段」只是一個首字母縮寫詞/快捷鍵。但我對定製IParameter實現更感興趣,這聽起來很有趣。所以,總之我可以提供額外的參數,一個盒裝會話ID。你能否概述一下我將如何解決基於此的新實例或現有實例?你的意思是: InScope(x => x.Parameters.FirstOrDefault(p => p.Name ==「SessionId」))? 其實你不需要實現一個新的IParameter,只需在調用Get時提供它。像Get (新參數(「SessionId」,_currentBoxedSessionId));對? –

+0

@RadekStrugalski你不需要一個自定義參數,但恕我直言,它只是一個更清潔。由你決定。 「boxed session id」 - 不,我會創建一個具有int字段的Session類。然後,您需要在應用程序中使用此類/對象來引用會話,而不僅僅是參數。如果你只是在參數中使用它,那麼沒有人會保留對它的引用,並且最終會得到......以及「未定義」的行爲。 – BatteryBackupUnit

+0

@RadekStrugalski,除非您提供[MCVE](https://stackoverflow.com/help/mcve),否則很難提供示例性實現來展示解決問題的方法。 – BatteryBackupUnit