我正在使用EntityFramework,并在一些后台作业类中实现通用存储库和工作单元模式。使用Unity DI创建作业类,以便可以注入依赖项,其中大多数是存储库和UnitOfWork对象。存储库和工作单元应该共享EF DbContext。
常见的作业如下:
所有的作业都在新任务中运行,类似于这样。
我已经使用
常见的作业如下:
public class CommonJob : IJob, IDisposable
{
private IRepo<SomeEntity> _repo;
private IUnitOfWork _uow;
public CommonJob(IRepo<SomeEntity> repo, IUnitOfWork uow)
{
_repo = repo;
_uow = uow;
}
public void RunJob()
{
// do stuff here
}
public void Dispose()
{
_uow.Commit();
_uow.Dispose();
}
}
所有的作业都在新任务中运行,类似于这样。
Task.Factory.StartNew(() => {
// container is UnityContainer
var job = container.Resolve<CommonJob>();
job.RunJob();
job.Dispose();
});
我已经使用
PerThreadLifetimeManager
将工作单元和存储库注册到Unity中,认为这样可以在一个任务的上下文中共享注册实例(以及在那个作业对象中),但不在外面。
我遇到的问题是有时作业将被注入处置对象,这显然不太好。我读到Task.Factory.StartNew()
并非总是使用新线程。这是否意味着PerThreadLifetimeManager
将在任务之间共享对象?如果是这样,是否有另一种管理统一对象生命周期的方法,允许每个任务在隔离状态下工作,而不管它正在运行的线程是什么?
编辑:
虽然下面选择的答案将实现相同的功能,但我最终使用了HierarchicalLifetimeManager
和子容器来为每个作业实现依赖项隔离。
这里是一个示例:
// registering the dependencies,
// these should be singletons, but only within the context of one job
_container.Register(typeof(IRepo<>), typeof(Repo<>), new HierarchicalLifetimeManager())
.Register<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
// starting a new job
Task.Factory.StartNew<IUnityContainer>(() =>
{
// create a child container to remove instance sharing between tasks
var childContainer = _container.CreateChildContainer();
// figure out and resolve the job class from the child container
// this will make sure that different jobs do not share instances
var jobType = GetJobType();
var job = childContainer.Resolve(jobType) as IJob;
job.RunJob();
return childContainer;
}).ContinueWith(previousTask => {
// when the job is done, dispose of the child container
task.Result.Dispose();
});
HieararchicalLiftetimeManager
并在任务中创建了一个子容器。这是因为我需要使用容器来动态解析某些作业类中的一些服务。我知道使用容器作为服务定位器是一种代码异味,但这就是它的设置方式,现在没有时间去修复它... - Ivan PintarHieararchicalLiftetimeManager
。 - Ivan Pintar