减少对SignalR,NHibernate和Ninject的依赖

本文关键字:Ninject 依赖 NHibernate SignalR | 更新日期: 2023-09-27 18:37:04

一个架构问题。我有一个很好的解耦 MVC3 解决方案,其中包含一些运行良好的项目。

Proj.Core           - interfaces for data classes and services
Proj.Services       - interfaces for model services
Proj.Data.NH        - implementations of the data interfaces
Proj.Services.NH    - implementations of the data / model services
Proj.Infrastructure - setting up Ninject and NHibernate
Proj.Tests          - unit tests
Proj.Web            - the MVC project
我已经将NHibernate

设置为基础设施项目中每个请求的会话,因此Proj.Web不需要引用NHibernate(或Ninject,就此而言)。我现在介绍 SignalR,它非常适合快速聊天应用程序。我在 Web 项目中放置了一个 SignalR 中心。我现在想将聊天消息保留在数据库中,这让我有些困惑。

我想使用一个服务(我们称之为PostService),因此 SignalR 中心不依赖于 NHibernate。我的其他服务被注入到控制器的构造函数中,会话被注入到服务的构造函数中。

由于 SignalR 中心闲置,与控制器不同,PostService(作为IPostService注入构造函数)不能将会话注入到其构造函数中,因为不会有会话。如果有的话,它将永远徘徊,这对于交易来说太长了。

我可以将会话工厂注入PostService,每个方法都可以使用一个事务,例如

private void WithTransaction(Action<ISession> action)
{
    using (var session = _sessionFactory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        action(session);
        tx.Commit();
    }
}
public IPost Post(string message)
{
    WithTransaction(session =>
        {
            session.Save(new Post(message));
        });
}

然后,集线器将调用_postService.Post(message);

但是,一旦 Post 方法执行更多操作,我将需要使用一些现有服务来执行这些操作,因为它们已经过编写和单元测试。由于会话是在该方法中创建的,因此我无法将服务注入到PostService构造函数中,因为它们接受会话到其构造函数中。

所以,我想我有以下选择,但我不确定 a) 这是一个完整的列表,还是 b) 哪个是最好的选择:

I. 将IDependencyResolver注入PostService构造函数,并在 Post 方法中创建我需要的服务,将会话传递给构造函数。System.Web.Mvc 和 SignalR 中有一个IDependencyResolver,因此这将(取决于PostService驻留的项目)引入对任一库的依赖关系。

II. 修改服务,使每个使用会话的方法都有一个作为参数传入。在没有会话参数的情况下重载它,并调用新的参数。MVC 服务调用将使用第一个,PostService将使用第二个,例如

public void SaveUser(IUser user) 
{
    Save(_session, user);
}
public void SaveUser(ISession session, IUser user) 
{
    session.Save(user);
}

三、不要使用现有服务。让PostService自己做,即使有一点重复(例如获取用户详细信息等)

IV. 从服务的构造函数中删除 ISession,并将其传递给每个方法(并相应地处理Controller

五、别的。

我想我倾向于第一个,但我不确定PostService会住在哪里。如果它进入Proj.Services.NH,那么我将不得不引入对System.Web.Mvc或SignalR的依赖,我不想这样做。如果它存在于Proj.Web中,那么我将不得不引入对NHibernate的依赖,我也不想这样做。它不属于 Proj.Infrastructure,因为它是应用程序代码。它应该有自己的项目,依赖于所有内容,还是有更好的方法?

减少对SignalR,NHibernate和Ninject的依赖

我会使用某种汽车工厂来提供您需要的其他服务。因此,您可以将PostService构造函数编写为:

public PostService( Func<INeededService1> factory1,Func<INeededService2> factory2 ...)
{
...
}

然后使用此扩展让这些工厂自动工作(通过查询容器)。