我有一个使用IoC和Unity的MVC应用程序,我使用DbContext
定义了PerRequestLifetimeManager
实现。该对象通过工作单元实现注入控制器。
container.RegisterType<DBContext, MyContext>(new PerRequestLifetimeManager());
到目前为止,一切都运行良好,应用程序拥有相当数量的模型和控制器。现在我最近要做的是为这个应用程序添加一些自动化任务,为此我想使用HangFire。
我已经在我的项目中设置了这个库并创建了一个简单的任务,我想调用一个需要DBContext
的动作。
RecurringJob.AddOrUpdate(() => MyTask(), Cron.Daily);
和MyTask()
定义如下
public void MyTask()
{
var taskManager = container.Resolve<ITaskManager>();
taskManager.DoSomething();
}
任务管理器需要一个DBContext实例(通过工作单元对象)
public class TaskManager : ITaskManager
{
public TaskManager(IUnitOfWork uow) {
...
}
}
public class UnitOfWork : IUnitOfWork
{
public class UnitOfWork(DBContext context) {
...
}
}
现在我遇到的问题是每当任务运行时我都会得到PerRequestLifetimeManager can only be used in the context of an HTTP request
的异常。
有没有办法可以在没有HTTP请求的情况下注入此对象,或者如何更改Unity配置以支持我的HangFire任务?
答案 0 :(得分:12)
对于这个问题,我已经不再使用PerRequestLifetimeManager
了。我现在开始使用HierarchicalLifetimeManager
而不是container hierarchies,然后你需要设置你的应用程序,以便为每个预期的范围(例如请求或作业)创建一个新的子容器,并在以后处置该子容器范围是完整的。
有一些库挂钩到MVC和WebAPI,以便为每个请求创建一个新的子容器。快速搜索发现这个MVC:Unity.Mvc5和官方Unity.AspNet.WebApi NuGet包中包含UnityHierarchicalDependencyResolver
。
要使其与您的任务应用程序一起使用,您必须使用自己的方法来创建子容器来控制范围,但这非常简单。只需致电IUnityContainer childContainer = container.CreateChildContainer()
,使用子容器解析您的实例并完成您的工作,然后在范围调用结束时childContainer.Dispose()
。