2013-06-06 33 views
4

我完成了Karl Shiffet的'InTheBox' WPF Training,發現它是學習WPF的極好資源。它提出的一件事是使用依賴注入和Unity容器。下面是提出的一些問題,我的代碼段:爲什麼要使用依賴注入容器?

public partial class App : Application { 

    protected override void OnStartup(StartupEventArgs e) { 

     IUnityContainer container = new UnityContainer(); 

     container.RegisterType<IDialogService, ModalDialogService>(
      new ContainerControlledLifetimeManager()); 

     container.RegisterType<IEventRepository, EventRepository>(
      new ContainerControlledLifetimeManager()); 

     MainWindow window = container.Resolve<MainWindow>(); 

     window.DataContext = container.Resolve<MainWindowViewModel>(); 

     window.Show(); 
    } 
} 

的依賴正在註冊到UnityContainer然後由UnityContainer注入MainWindowViewModel。我的問題是爲什麼使用容器?爲什麼不直接使用下面的一段代碼,就依賴注入而言達到了同樣的事情:

protected override void OnStartup(StartupEventArgs e) 
{ 
    IDialogService dialogService = new ModalDialogService(); 
    IEventRepository eventRepository = new EventRepository(); 

    MainWindow window = new MainWindow(); 
    window.DataContext = 
     new MainWindowViewModel(eventRepository, dialogService); 
    window.Show(); 
} 

我仍然注入的依賴項由該組合物根的構造,所以我看到在這種情況下沒有任何好處使用UnityContainer。

我很欣賞它明顯存在的原因,但有人可以解釋在這種情況下是否增加了什麼?另外,還有另外一種情況,像這樣使用容器真的是一件容易的事情嗎?

回答

5

在像這樣的簡單情況下使用DI容器對你來說並沒有多大作用。當事情變得更加複雜時它開始變得更有意義,並且它還將依賴性變化的影響降到最低。

舉個例子,你有一個ILoggingService,你現在使用的所有依賴關係。使用Unity等DI容器時,只需添加一行代碼即可。

protected override void OnStartup(StartupEventArgs e) 
    { 
     IUnityContainer container = new UnityContainer(); 
     container.RegisterType<IDialogService, ModalDialogService>(); 
     container.RegisterType<IEventRepository, EventRepository>(); 
     container.RegisterType<ILoggingService, LoggingService>(); // added 

     MainWindow window = container.Resolve<MainWindow>(); 
     window.DataContext = container.Resolve<MainWindowViewModel>(); 
     window.Show(); 
    } 

當你自己做,你必須添加一行代碼,並修改3行代碼。

protected override void OnStartup(StartupEventArgs e) 
    { 
     ILoggingService loggingService = new LoggingService(); // added 
     IDialogService dialogService = new ModalDialogService(loggingService); // modified 
     IEventRepository eventRepository = new EventRepository(loggingService); // modified 

     MainWindow window = new MainWindow(); 
     window.DataContext = new MainWindowViewModel(eventRepository, dialogService, loggingService); // modified 
     window.Show(); 
    } 

當使用更高級的容器可以掃描要註冊的類型時,您可能不必更改組合根中的任何代碼。這裏是一個使用AutoFac的例子。

protected override void OnStartup(StartupEventArgs e) 
    { 
     var builder = new ContainerBuilder(); 
     var assembly = Assembly.GetExecutingAssembly(); 
     builder.RegisterAssemblyTypes(assembly) 
       .AsSelf() 
       .AsImplementedInterfaces(); 
     var container = builder.Build(); 

     MainWindow window = container.Resolve<MainWindow>(); 
     window.DataContext = container.Resolve<MainWindowViewModel>(); 
     window.Show(); 
    } 
+0

感謝您的額外示例,展示了在引入新的依賴關係時容器如何不允許代碼更改。 –

2

你說得很好。你的第二個例子是使用Mark Seemann可能提到的'窮人的DI'。這仍然是DI,但你自己做。

當您開始管理許多不同類型和功能(如生活方式管理)的注入並且按照慣例註冊類型時,IoC容器會成爲他們自己的大量勞動力儲戶。

對於具有最小依賴管理的較小任務,正如您所建議的,它們可能是矯枉過正的。

如果你想了解更多,我會強烈推薦Seemann的書和博客。恕我直言,他比任何人都更好地解釋了這個話題。

+0

感謝您花時間回答我在考慮擴展依賴注入方法時考慮Seemann的書。 –

+0

我也推薦這本書。我還沒有完成它,但我已閱讀的部分是有幫助的。 –