2012-04-15 89 views
2

我正在尋找在新解決方案中使用IoC容器(如StructureMap)。該解決方案的項目如下:依賴注入 - 分層應用程序

  • Desktop.UI
  • Desktop.Models
  • Desktop.Views
  • Desktop.Presenters
  • BusinessLogic
  • 的BusinessObjects
  • 數據訪問

其中Desktop.Models,BusinessLogic和DataAccess都具有對BusinessObjects的引用。

Desktop.UI項目將成爲DI應該配置的入口點,但我並不想僅爲DI添加對DataAccess的引用。

我已經看到了一些其他問題沿着這些線上的SO和一個答案是爲IoC創建一個單獨的項目,引用相關的項目,然後從Desktop.UI引用IoC項目。然而,Desktop.UI需要DI配置來實例化視圖的演示者,因此不確定單獨的項目是否可行。

我已經看到了一些定義註冊表類並使用StructureMap掃描功能自動檢測註冊表類的基本示例。我的第一個想法是將這些註冊表類放在他們正在配置的項目中,但是這會導致所有項目都必須引用StructureMap。

建議在分層應用程序中設置DI的方法是什麼?

+0

如果我是你,我會創建一個框架項目來存儲一個單獨的IoC,有你在那裏引導捆綁代碼。 – 2012-04-15 09:02:55

+0

@jameslewis對於UI項目來說,如何使用UI項目,因爲如果IoC是在UI引用的單獨項目中,那麼IoC項目不能引用UI,那麼UI項目需要DI提供者? – 2012-04-15 09:09:19

回答

1

根據我的經驗,我發現我在服務器端代碼中使用了一種形式的依賴注入,而在我的客戶端代碼中使用了一種。例如,WinForms項目我正在研究最近在服務器端(業務邏輯,數據訪問)和客戶端智能客戶端軟件工廠使用的Unity(包括它自己形式的DI的winforms的MVP框架)。所以在你的例子中,我想說如果你試圖讓DI框架跨越你的應用程序的所有層來工作,那是因爲你不應該這樣做。你可能有一種情況,你想要有兩種形式的DI,一種用於客戶端,一種用於服務器。

除此之外,我認爲我是正確的說大多數DI框架允許您在配置文件中引導您的依賴關係。配置文件告訴框架有關你的依賴關係的一切,包括它們所在的組件。這意味着你不需要引用實例化你的IoC容器的項目中的任何實際項目。所以在我的一個Framework項目的例子中,你將有一個實例化你的IoC容器的單例,並從配置文件中讀取所有的依賴關係。

下面是一些鏈接給你:

希望一些幫助!

問候,

詹姆斯

+0

感謝您的回覆。我的桌面客戶端,業務邏輯和數據訪問項目都在這個解決方案中一起部署,所以仍然可以使用流利的語法而不是配置文件分別配置它們,或者如果我不想配置文件,從UI引用數據訪問? – 2012-04-15 11:39:48

+0

我會去配置文件。就我個人而言,我們編寫了一個更智能的引導程序,它使用反射來解析依賴關係,所以我暫時還沒有使用過配置方法(並且我們也沒有引用程序集的問題)。但我會說脫鉤的一切是配置選項在那裏,所以這聽起來像你的情況這是要走的路。 – 2012-04-15 12:07:50

+0

@MattF我絕對不會使用配置文件。維護開銷太大。此外,它更容易出錯。 http://martinfowler.com/articles/injection.html#CodeOrConfigurationFiles看看我的答案。 – Rookian 2012-04-15 15:39:11

1

對於WindowsForms我有我的IoC的東西,一個單獨的項目。我稱之爲CompositionRootCompositionRoot(啓動項目)的

切入點:

public static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     BootsTrapper.Boot(); 

     using (var mainForm = ObjectFactory.GetInstance<IPresenter<IMainView>>()) 
     { 
      Application.Run((Form)mainForm.CurrentView); 
     } 
    } 
} 

BootsTrapper負責在註冊,是CompositionRoot的一部分。

MainViewPresenter顯示第一個窗體。 MainViewPresenter可以使用包含抽象演示者工廠的外觀服務IMainViewPresenterFacade來顯示其他表單。

public class MainViewPresenter : Presenter<IMainView> 
{ 
    readonly IArticleRepository _articlesRepository; 
    readonly IMainViewPresenterFacade _presenterFactory; 
    readonly IUnitOfWork _unitOfWork; 

    public MainViewPresenter(IMainView currentView, IArticleRepository articlesRepository, IUnitOfWork unitOfWork, 
          IMainViewPresenterFacade presenterFactory) 
     : base(currentView, unitOfWork) 
    { 
     _articlesRepository = articlesRepository; 
     _unitOfWork = unitOfWork; 
     _presenterFactory = presenterFactory; 

     Ensure.That(articlesRepository).IsNotNull(); 
     Ensure.That(presenterFactory).IsNotNull(); 

     CurrentView.DetailsClick += View_DetailsClick; 
     CurrentView.CloseClick += ViewCloseClick; 
     CurrentView.CreateClick += View_CreateClick; 
     CurrentView.DeleteClick += View_DeleteClick; 

     CurrentView.BindModel(_articlesRepository.GetAll().Select(x => new ArticleViewModel { Id = x.ArticleId, Name = x.Description })); 
    } 

    public override void Dispose() 
    { 
     base.Dispose(); 

     CurrentView.DetailsClick -= View_DetailsClick; 
     CurrentView.CloseClick -= ViewCloseClick; 
     CurrentView.CreateClick -= View_CreateClick; 
     CurrentView.DeleteClick -= View_DeleteClick; 
    } 

    void View_DeleteClick(object sender, EventArgs e) 
    { 
     var selectedArticle = CurrentView.GetSelectedArticle(); 
     var article = _articlesRepository.GetById(selectedArticle.Id); 
     _articlesRepository.Delete(article); 
     _unitOfWork.Commit(); 
    } 

    void View_CreateClick(object sender, EventArgs e) 
    { 
     using (var createPresenter = _presenterFactory.CreateCreatePresenter()) 
     { 
      ShowDialog(createPresenter.CurrentView, CurrentView); 
     } 
    } 

    void ViewCloseClick(object sender, EventArgs e) 
    { 
     CurrentView.Close(); 
    } 

    void View_DetailsClick(object sender, EventArgs eventArgs) 
    { 
     var article = CurrentView.GetSelectedArticle(); 

     if (article == null) return; 

     using (var detailPresenter = _presenterFactory.CreateDetailPresenter(article)) 
     { 
      ShowDialog(detailPresenter.CurrentView, CurrentView); 
     } 
    } 
} 

看看我的SimpleMVP項目或在這個問題Dependency Injection and project structure for Console applications並隨時提出進一步的問題:)