2

我的公司使用Unity容器與代碼作爲配置在桌面應用程序。閱讀本書Dependency Injection in .NET後,我想提出在配置使用公約自動註冊因爲書上說使用組成根撰寫應用程序的對象圖,你應該更喜歡自動登記(以避免違反乾和獲得更多的可管理的代碼)。.NET依賴注入自動註冊與性能

但我也看了pluralsight當然Building High-Performance Windows 8 Applications和筆者說:

的組件負載是昂貴的過程,至於性能問題,並避免在啓動路徑組件的不必要的負荷是很重要的。

我擔心在啓動時使用自動註冊的性能,因爲它需要使用反射和加載所有程序集。

我喜歡瞭解什麼是最好的方法。有沒有人遇到過性能問題,並放棄了自動註冊或找到中間選項?

回答

3

如果使用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); 
} 

現在,讓我們說,ProductRepositoryUserRepository各自生活在不同的組件。現在,當第一次調用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容器時,也有延遲加載程序集的方法,但這是一種相當複雜的做法,除非有實際的性能損失並且無法在任何其他方式。

+1

感謝Steaven的解釋。我應該在擔憂之前衡量表現。 – user7699285