【问题标题】:3 Tier Architecture with NHibernate, Ninject and Windows Forms具有 NHibernate、Ninject 和 Windows 窗体的 3 层架构
【发布时间】:2015-02-03 11:34:26
【问题描述】:

所以我正在重构一个由通过 NHibernate 访问的 SQLite 数据库支持的中小型 Windows 窗体应用程序。当前的解决方案仅包含一个 App 项目和一个 Lib 项目,因此它的结构不是很好,并且在很多地方都紧密耦合。

我从this answer 中的结构开始,但后来遇到了一些问题。

  1. 数据库初始化: 由于构建 NHibernate SessionFactory 的代码位于 DAL 中,并且我需要将 ISession 注入到我的存储库中,因此我需要在我的 Forms 项目中直接引用 DAL 和 NHibernate 才能使用 Ninject 设置 DI(应该这样做在应用程序项目/表示层中对吗?)

这难道不是我试图通过这种架构避免的事情之一吗?

在理想世界中,哪些项目应该相互引用?

  1. 一般的 DI: 我很难弄清楚如何正确地进行 DI。我读到了使用组合根只有一个地方可以直接使用 Ninject 容器,但这与当前使用 NHibernate Sessions 的方式并不能很好地配合。 我们有一个MainForm,它显然是应用程序的入口点,并在其整个生命周期内保持一个会话。此外,用户可以打开多个SubForms(主要但不限于)用于编辑单个实体)当前每个实体都有一个单独的会话,生命周期较短。这是通过静态 Helper 公开 SessionFactory 并根据需要打开新 Session 来完成的。

除了组合根模式之外,还有另一种在 Windows 窗体中使用 DI 的方法吗?

如何利用 Ninjects 功能进行范围注入,以按表单管理我的 NHibernate 会话(如果可能的话)?

  1. 术语: 我对什么是RepositoryService 有点困惑。对已发布答案的一条评论指出“存储库可以包含业务逻辑,在这种情况下您可以将其称为服务”。当我们经常想将过滤等推送到数据库中时,我们的存储库只包含基本的 CRUD 操作,感觉有点没用。所以我们继续使用GetByName 或更复杂的GetAssignmentCandidates 等方法扩展存储库。感觉很合适,因为实现是在业务层中,但它们仍然被称为存储库。我们还使用了Controllers 用于直接与 UI 元素交互的类,但我认为这个名称在网络世界中更常见。

我们的Repositories 真的应该叫Services吗?

对不起,文字墙。任何答案将不胜感激!

【问题讨论】:

    标签: c# winforms nhibernate dependency-injection ninject


    【解决方案1】:

    关于1: 是和不是。是的,您希望 UI 层不依赖于 x 层的某些细节。但事实并非如此。组合根只是驻留在同一个程序集中,逻辑上它不是同一层。

    关于 2: 限制容器的使用。工厂(对于会话,..)有时是必要的。应避免使用static。但是,某些框架会阻止您使用理想的设计。在这种情况下,尽量近似。 如果您目前可以使用new FooForm(),那么您可以将其替换为 DI 或 DI 工厂(例如ninject.extensions.Factory)。如果您完全无法控制类型的实例化方式,那么您需要使用static 像服务定位器一样访问内核,然后“定位”直接依赖项(而间接依赖项由 DI 容器注入到直接依赖项中) )。

    关于 3:我认为这有点争议,可能经常被误解。我不认为你调用你的类真的很重要(当然是,但你的代码库的一致性比决定将它们命名为存储库还是服务更重要),什么是重要的是你如何设计他们的职责和关系。 因此,我自己更喜欢在-Query 命名类中提取过滤器和东西,每个类都提供一种方法。但其他人有其他偏好......我认为关于这个主题的博客文章等已经足够多,在这里重新散列是没有用的。

    【讨论】:

    • 感谢您的详细回复。
    • 编辑我的评论花了太长时间。第 2 部分特别有用。如果我理解正确,我会在(子)表单中明确列出我的依赖项,并使用工厂进行初始创建,类似于在 Program.cs 中创建 MainForm。然后(在我的例子中)Ninject 提供的工厂也可以解析它们的依赖图并注入它们。关于命名:我认为确切地称呼它们并不是什么大问题。我只是确保不“违反”任何既定惯例。
    • 重新出厂:是的。关于命名约定:好吧,也许它们已经建立起来了,但我打赌它们会经常相当被误解和破坏。因此,与其坚持他们,我会选择并定义一个对您的团队有意义的并记录它。
    【解决方案2】:

    实现像您这样的情况的最佳实践是使用 MVP 设计模式。这是我可以提供给您的架构。

    1. MyApp.Infrastructure // 基础层 - 无参考
    2. MyApp.Models // 域层 - 对基础架构的引用
    3. MyApp.Presenter // 像 MVC 中的控制器一样 - 引用服务、模型,
    4. MyApp.Repository.NH // DAL 层 - 对模型、基础架构的引用
    5. MyApp.Services // BLL 层 - 对存储库、模型的引用
    6. MyApp.Services.Cache // 缓存 BLL 层(极力推荐)- 引用服务、模型
    7. MyApp.UI.Web.WebForms // UI 层 - 对所有层的引用

      我会尽量以'Category'模型的基本实现为例进行说明。

    -基础设施-

    • EntityBase.cs
    • BussinesRule.cs
    • IEntity.cs
    • IRepository.cs

    -模型-

    类别(文件夹)

    • Category.cs // 实现 IEntity 并从 EntityBase 派生
    • ICategoryRepository.cs // 实现 IRepository

    -演示者-

    接口

    • IHomeView.cs // 放置你需要的所有属性和方法。

    • ICategoryPresenter.cs

    实现

    • CategoryPresenter.cs // 实现 ICategoryPresenter

      CategoryPresenter(IHomeView view, ICategorySevice categorySevice){

      }

    -存储库-

    存储库(文件夹)

    • GenricRepository.cs // 实现 IRepository
    • CategoryRepository :实现 ICategoryRepository 并派生自 GenricRepository

    -服务-

    接口

    • ICategorySevice.cs
    • AddCategory(类别模型);

    实现

    • CategorySevice.cs // 实现 ICategorySevice
    • CategorySevice(ICategoryRepository categoryRepository ){}

      AddCategory(类别模型){ // 通过 ICategoryRepository 实现人员。 }

    -Services.Cache-

    // 这一切都取决于您的选择.. Radis 或 Web 缓存..

    -UI.Web.WebForms-

    Views - Home(Folder) // 实现类似于 MVC 视图中的结构。 Index.aspx // 实现 IHomeView

        Page_Init(){
            // Get instance of Presenter
            var categoryPresenter = CategoryPresenter(this, new CategorySevice);
       }
    

    我不确定你的问题是否正确,但也许能给你一个想法:)

    【讨论】:

    • 我不认为这个例子真的适合我的问题,因为我们正在开发一个 Windows 窗体应用程序并且没有 ASP.NET 网页。不过还是谢谢你的文章。
    • @MrFloya,亲爱的兄弟,你使用 MVP 的 UI 并不重要:) MVP 模式非常适合 Web 窗体和 WinForms。只需在 FormLoad 或 FormInit 事件中获取演示者的实例即可。我强烈建议您搜索 MVP。
    • 你是对的。抱歉,我最初只是浏览了您的解决方案。实际上,我们当前的结构与 MVP 非常相似,只是命名约定有点不同。
    猜你喜欢
    • 2011-05-16
    • 2017-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多