我正在使用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();
});
答案 0 :(得分:6)
由于并行库使用线程池,因此您将获得处置对象,Unity会为池的同一线程返回相同的对象。
如果您按照发布的方式使用容器,建议您使用PerResolveLifetimeManager。这样,当您解析一个对象时,整个解析图共享同一个实例,但每个分辨率的实例都是唯一的:每个任务在调用Resolve
时都有自己的实例。