依赖注入 - 分层应用

时间:2012-04-15 08:59:49

标签: .net dependency-injection inversion-of-control

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

  • 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配置来实例化视图的演示者,因此不确定单独的项目是否有效。

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

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

2 个答案:

答案 0 :(得分:1)

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

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

以下是您的一些链接:

希望其中一些有帮助!

此致

詹姆斯

答案 1 :(得分: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来显示其他表单。

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,随时提出进一步的问题:)