2

一个建筑问题。我有一个很好的解耦 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)这是最好的选择:

IDependencyResolver一、在构造函数中注入an PostService,在方法中创建自己需要的服务Post,将session传入构造函数。System.Web.Mvc 和 SignalR 中有一个IDependencyResolver,因此这将(取决于PostService所在的项目)引入对任一库的依赖。

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

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

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

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

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

V. 别的东西。

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

4

1 回答 1

3

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

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

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

于 2012-06-13T10:24:18.330 回答