我有一个关于如何在ASP.NET mvc应用程序和Windows服务中使用相同DI代码的问题,因为它们都使用NHibernate与同一个数据库进行交互。然而,Windows服务执行后台任务。
与每个人一样,我有一个新的控制器工厂,它知道如何使用StructureMap实例化控制器。因此,我可以将所需的存储库作为其构造函数的参数提供给我的控制器。由于Structuremap使用HTTPContextScope控制ISession生命周期,因此我可以确保所有存储库都为每个Web请求接收相同的ISession实例。
然而,在Windows服务和使用Structuremap(相同的DI代码)中,我不知道一种很好的方法来逻辑隔离不同的后台任务以拥有一个独特的ISession实例并与它们使用的存储库共享它。我希望同时执行多个任务,因此ISession不能是单个对象(如使用NHibernate的桌面应用程序所推荐的那样)。
我想在我的Windows服务信任Structuremap中保留并引入One Session Per Request模式,为每个Task提供相同的ISession实例。有人能指出我正确的方向吗?
由于
Corey Coogan这两部分的帖子非常符合我认为应该解决的问题。但是我对WCF并不熟悉,并且往往会对文章中的部分感到困惑。
http://blog.coreycoogan.com/2010/05/26/structuremap-wcf-nhibernate-part-1/ http://blog.coreycoogan.com/2010/05/27/structuremap-wcf-nhibernate-part-2/
答案 0 :(得分:0)
我认为你可以使用ThreadLocal Lifeycle。我自己从未使用它,但它听起来像你在寻找:
PerRequest - 默认操作。一个 将为每个实例创建新实例 请求。单身人士 - 单身 实例将在所有人之间共享 请求
ThreadLocal - 将为每个请求线程创建一个实例。 使用缓存实例 ThreadLocalStorage。
HttpContext - 单个实例将 为每个HttpContext创建。 缓存中的实例 HttpContext.Items集合。
HttpSession - 单个实例会 为每个HttpSession创建。 缓存中的实例 HttpContext.Session集合。使用 慎用。
Hybrid - 如果使用HttpContext存储 它存在,否则使用ThreadLocal 存储
答案 1 :(得分:0)
在我的Windows服务中,我有一个与ASP.NET MVC中的引导程序完全相同的引导程序:
public static class Bootstrapper
{
public static void Initialize()
{
StructureMap.ObjectFactory.Initialize(cfg =>
{
cfg.UseDefaultStructureMapConfigFile = false;
cfg.IgnoreStructureMapConfig = true;
cfg.AddRegistry<Web.Core.DI.NhibernateRegistry>();
cfg.AddRegistry<Web.Core.DI.DomainRegistry>();
cfg.AddRegistry<Web.Core.DI.ServicesRegistry>();
cfg.AddRegistry<Web.Core.DI.QuartzRegistry>();
});
ServiceLocator.SetLocatorProvider(() => new StructureMapServiceLocator(ObjectFactory.Container));
}
}
然后我为每个模块定义了一个注册表:
public class NhibernateRegistry: Registry
{
public NhibernateRegistry()
{
SchemaOperation schemaOperation = SchemaOperation.None;
For<ISessionFactory>()
.Singleton()
.Use(new BpReminders.Data.NH.NHibernateSessionFactory(connectionString, schemaOperation).SessionFactory);
For<IUnitOfWork>()
.HybridHttpOrThreadLocalScoped()
.Use<BpReminders.Data.NH.UnitOfWork>();
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(o => ((BpReminders.Data.NH.UnitOfWork)o.GetInstance<IUnitOfWork>()).CurrentSession);
}
}
我在服务启动后立即启动所有内容:
protected override void OnStart(string[] args)
{
Bootstrapper.Initialize();
}
最后我采用了Singleton模式,因为我的Windows服务不使用任何额外的线程。 我知道StructureMap有一个关键字AlwaysUnique,它可能对你要做的事情有用:
For<ISession>()
.AlwaysUnique()
代码评论说(关于AlwaysUnique)
///强制StructureMap始终使用唯一的实例来实现 ///停止“BuildSession”缓存
你必须深入研究这个原因我刚做了几次测试。不多。