使用SignalR,NHibernate和Ninject减少依赖性

时间:2012-06-13 10:06:06

标签: c# nhibernate dependency-injection signalr

一个架构问题。我有一个很好的去耦合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,它非常适合快速聊天应用程序。我在网络项目中放置了一个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)哪个是最好的选择:

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

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

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

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

III。不要使用现有服务。让PostService做自己的事情,即使有一些重复(例如获取用户详细信息等)。

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

诉别的。

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

1 个答案:

答案 0 :(得分:3)

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

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

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