2

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

  • 桌面.UI
  • 桌面模型
  • 桌面视图
  • Desktop.Presenters
  • 商业逻辑
  • 业务对象
  • 数据访问

其中 Desktop.Models、BusinessLogic 和 DataAccess 都引用了 BusinessObjects。

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

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

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

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

4

2 回答 2

1

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

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

这里有一些链接给你:

希望其中的一些帮助!

问候,

詹姆士

于 2012-04-15T11:11:47.930 回答
1

对于 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包含抽象 Presenter 工厂的外观服务来显示其他表单。

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并随时提出更多问题 :)

于 2012-04-15T15:05:40.350 回答