依赖关系注入 - 分层应用程序



我希望在新的解决方案中使用IoC容器,例如StructureMap。解决方案项目如下:

  • 桌面.用户界面
  • 桌面模型
  • 桌面视图
  • 桌面演示者
  • 业务逻辑
  • 业务对象
  • 数据访问

其中 Desktop.Models、BusinessLogic 和 DataAccess 都有对 BusinessObject 的引用。

Desktop.UI 项目将是应该配置 DI 的入口点,但我真的不想仅为 DI 添加对 DataAccess 的引用。

我在SO上看到了其他一些类似的问题,一个答案是为IoC创建一个单独的项目,该项目引用相关项目,然后从Desktop.UI引用IoC项目。 但是,Desktop.UI 需要 DI 配置来实例化视图的演示者,因此不确定单独的项目是否有效。

我已经看到了定义注册表类和使用结构映射扫描功能自动检测注册表类的一些基本示例。我的第一个想法是将这些注册表类放在他们正在配置的项目中,但这会导致所有项目都必须引用 StructureMap。

在分层应用程序中设置 DI 的推荐方法是什么?

根据我的经验,我发现我在整个服务器端代码中使用了一种形式的依赖注入,在我的客户端代码中使用了一种。 例如,我正在处理的 WinForms 项目最近在服务器端(业务逻辑、数据访问)使用了 Unity,在客户端使用了智能客户端软件工厂(包含自己的 DI 形式的 winforms 的 MVP 框架)。 所以在你的例子中,我想说,如果你在尝试让 DI 框架跨应用程序的所有层工作时遇到困难,那是因为你不应该这样做。 您可能遇到过这样一种情况,即您希望拥有两种形式的 DI,一种用于客户端,一种用于服务器。

除此之外,我认为我说得对,大多数 DI 框架都允许您在配置文件中引导依赖项。 配置文件告诉框架有关依赖项的所有信息,包括它们所在的程序集。 这意味着无需在实例化 IoC 容器的项目中引用任何实际项目。 因此,在我的框架项目中,您将有一个实例化 IoC 容器并从配置文件中读取所有依赖项的单一实例。

以下是为您提供的一些链接:

  • 统一:http://unity.codeplex.com/
  • Unity 配置设置
  • :有关 Unity 配置设置的堆栈溢出问题

希望其中一些有所帮助!

问候

詹姆斯

对于WindowsForms,我有一个单独的项目来管理我的IoC内容。我称之为CompositionRoot。

CompositionRoot(启动项目)的入口点:

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 项目或这个问题 依赖注入和控制台应用程序的项目结构,并随时提出进一步的问题:)

最新更新