C# 具有NHibernate、Ninject和Windows窗体的3层体系结构 p>所以我正处于一个由NHiBiite访问的SQLite数据库支持的小到中等大小的Windows窗体应用程序的中间。当前的解决方案只包含一个App项目和Lib项目,因此在许多地方它的结构不是很好,并且紧密耦合

C# 具有NHibernate、Ninject和Windows窗体的3层体系结构 p>所以我正处于一个由NHiBiite访问的SQLite数据库支持的小到中等大小的Windows窗体应用程序的中间。当前的解决方案只包含一个App项目和Lib项目,因此在许多地方它的结构不是很好,并且紧密耦合,c#,winforms,nhibernate,dependency-injection,ninject,C#,Winforms,Nhibernate,Dependency Injection,Ninject,我开始时的结构类似于,但后来遇到了一些问题 DB初始化: 由于构建NHibernate SessionFactory的代码位于DAL中,我需要将ISession注入我的存储库,因此我需要直接在表单项目中引用DAL和NHibernate,以便能够使用Ninject设置DI(这应该在应用程序项目/表示层中完成,对吗?) 对于这样的架构,这不是我试图避免的事情之一吗 在理想世界中,哪些项目应该相互参照 DI一般情况下: 我很难弄清楚如何正确地进行DI。我读过关于使用复合根目录只在一个地方直接使用Nin

我开始时的结构类似于,但后来遇到了一些问题

  • DB初始化: 由于构建NHibernate SessionFactory的代码位于DAL中,我需要将ISession注入我的存储库,因此我需要直接在表单项目中引用DAL和NHibernate,以便能够使用Ninject设置DI(这应该在应用程序项目/表示层中完成,对吗?)
  • 对于这样的架构,这不是我试图避免的事情之一吗

    在理想世界中,哪些项目应该相互参照

  • DI一般情况下: 我很难弄清楚如何正确地进行DI。我读过关于使用复合根目录只在一个地方直接使用Ninject容器的文章,但这与当前使用NHibernate会话的方式不太合适。 我们有一个
    MainForm
    ,它显然是应用程序的入口点,在其整个生命周期中保持一个会话。此外,用户还可以打开多个子表单(主要但不限于)以编辑单个实体),每个子表单当前都有一个单独的会话,且生命周期较短。这是通过一个静态助手公开SessionFactory并根据需要打开新会话来完成的
  • 除了复合根模式之外,还有其他方法可以在Windows窗体中使用DI吗

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

  • 术语: 对于什么是
    存储库
    服务
    ,我有点困惑。在发布的回答中有一条评论说“存储库包含业务逻辑是可以的,在这种情况下,您可以称之为服务”。当我们经常想将过滤等推送到数据库中时,我们的存储库只包含基本的CRUD操作,这让人觉得有些无用。因此,我们继续使用
    GetByName
    或更复杂的
    GetAssignmentCandidates
    等方法扩展存储库。这感觉很合适,因为实现在业务层,但它们仍然被称为存储库。对于直接与UI元素交互的类,我们使用了
    控制器
    ,但我认为这个名称在Web世界中更为常见
  • 我们的
    存储库
    真的应该被称为
    服务

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

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

    关于2: 限制容器的使用。工厂(对于会话,…)有时是必要的。应避免使用
    静态
    。然而,有些框架阻止您使用理想的设计。在这种情况下,请尽可能接近。 如果您当前可以执行
    new FooForm()
    ,那么您可以用DI或DI工厂(p.Ex.)来替换它。如果您完全无法控制类型实例化的方式,那么您需要使用
    static
    像服务定位器一样访问内核,然后“定位”直接依赖项(而间接依赖项由DI容器注入直接依赖项)

    关于3:我认为这有点争议,可能经常被误解。我不认为你所称的类真的那么重要(当然是这样,但是代码库的一致性比决定是否将它们全部命名为存储库或服务更重要),重要的是你如何设计它们的责任和关系。
    因此,我自己更喜欢在
    -Query
    命名类中提取过滤器和内容,每个类只提供一个方法。但其他人有其他偏好。。。我认为已经有足够多的关于这个主题的博客帖子等,在这里重新讨论是没有用的。

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

  • MyApp.Infrastructure//基础层-无参考
  • MyApp.Models//域层-对基础架构的引用
  • MyApp.Presenter//就像MVC中的控制器一样-引用服务、模型、
  • MyApp.Repository.NH//DAL层-模型、基础设施的参考
  • MyApp.Services//BLL层-对存储库、模型的引用
  • MyApp.Services.Cache//Cached BLL层(极为推荐)-参考服务、模型
  • MyApp.UI.Web.WebForms//UI层-对所有层的引用

    我将尽力以“类别”模型的基本实现为例进行解释

  • -基础设施-

    • EntityBase.cs
    • businesrule.cs
    • 电子商务
    • IRepository.cs
    -型号-

    类别(文件夹)

    • Category.cs//实现Entityity并从EntityBase派生
    • ICategoryRepository.cs//实现IRepository
    -演示者-

    接口

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

    • ICategoryPresenter.cs

    实施

    • CategoryPresenter.cs//Implements ICategoryPresenter

      CategoryPresenter(IHomeView视图,iCategoryService类别设备){

      }

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