如果使用DI容器一樣團結,你基本上已經註冊的依賴two options:使用過配置
用自動註冊你通常應用程序集掃描並反映給定的一組程序集中的類型。這批處理寄存器容器中的所有這些類型。
另一方面,顯式註冊時,您將以代碼(或XML或任何其他形式)逐個列出所有類型。
但是,這兩個選項都會導致包含類型的所有程序集註冊,以便在應用程序啓動時加載。
這是使用DI容器時通常難以防止的事情,因爲DI容器需要這些映射。典型的用途是在啓動時配置容器,之後只能從容器中解決。
另一方面,與Pure DI,它是更容易延遲裝配加載,直到這些類型第一次使用。
例如說你正在構建與純DI一個MVC的Web應用程序,它可能看起來有點像這樣:
public static Controller CreateController(Type type)
{
var dbContext = new CommerceContext(this.connectionString);
if (type == typeof(HomeController))
return
new HomeController(
new ProductRepository(
dbContext));
if (type == typeof(LogoutController))
return
new LogoutController(
new UserRepository(
dbContext));
else
return base.CreateController(type);
}
現在,讓我們說,ProductRepository
和UserRepository
各自生活在不同的組件。現在,當第一次調用CreateController
方法時,這將在啓動後很短時間內執行,此方法將被打亂。當一個方法獲得JITted時,所有引用類型的所有程序集都將被加載。在這種情況下,這意味着ProductRepository
的組件和UserRepository
的組件都將被加載。
由於HomeController
極有可能產生很快的應用程序啓動後,就沒有太大的意義,試圖延緩ProductRepository
組件的負荷,但它可能是有意義的UserRepository
,因爲LogoutController
可能會產生多大後來在應用程序的生命週期中。
我們可以防止UserRepository
組件被加載,通過將其解壓縮到它自己的方法:
public static Controller CreateController(Type type)
{
...
if (type == typeof(LogoutController))
return
new LogoutController(
CreateUserRepository(dbContext));
...
}
// Extracted to method to enable lazy assembly loading
private IUserRepository CreateUserRepository(CommerceContext context)
{
return new UserRepository(dbContext));
}
通過委派的UserRepository
類的創建到CreateUserRepository
方法,我們可以防止其裝配被裝入了早。這顯然只適用於以前不需要該組件的其他類型。例如,如果IUserRepository
接口是在同一個組件中定義的,這意味着在CreateController
獲取JIT時,該組件仍將被加載,因爲CreateController
取決於IUserRepository
。
然而,這個例子有點設計,因爲對於一個Web應用程序來說,做這種延遲加載程序集通常沒什麼意義,因爲還有其他技術可以防止用戶注意到應用程序的啓動時間。
這使我以下,儘管它可能是延緩的應用程序加載在桌面應用程序重要的是,你真的需要衡量這個第一。在很多應用中,這個絕對不是問題。我自己研究了幾個桌面應用程序,這些應用程序都使用DI和DI容器,並在啓動時對所有組件進行了預加載,在大多數情況下,性能並不是問題。
在其他(單一)情況下,這實際上是一個問題,我們通過顯示一個花哨的啓動畫面來顯示用戶應用程序正在加載來解決這個問題。
即使在使用DI容器時,也有延遲加載程序集的方法,但這是一種相當複雜的做法,除非有實際的性能損失並且無法在任何其他方式。
感謝Steaven的解釋。我應該在擔憂之前衡量表現。 – user7699285