Używam EntityFramework
i implementuję ogólny wzorzec repozytorium i jednostki pracy w grupie klas zadań w tle. Klasy zadań są tworzone przy użyciu Unity DI, dzięki czemu mogą zostać wstrzyknięte zależności, które w większości są repozytoriami i obiektem UnitOfWork
. Repozytoria i jednostki pracy powinny współdzielić EF DbContext
.Unity PerThreadLifetimeManager i zadania
Wspólna praca będzie wyglądać następująco:
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();
}
}
Wszystkie zadania są uruchamiane w nowych zadań, coś takiego
Task.Factory.StartNew(() => {
// container is UnityContainer
var job = container.Resolve<CommonJob>();
job.RunJob();
job.Dispose();
});
A ja zarejestrował unit-of-pracy i repozytoriów z Unity przy użyciu PerThreadLifetimeManager
, myśląc, że to pozwoliłoby na współdzielenie zarejestrowanych instancji w kontekście jednego zadania (i jednego obiektu zadania), ale nie na zewnątrz.
Kwestia, którą mam, polega na tym, że czasami prace zostaną wstrzyknięte rozrzuconymi przedmiotami, co oczywiście nie jest zbyt miłe. Czytałem, że Task.Factory.StartNew()
nie zawsze używa nowego wątku. Czy to oznacza, że PerThreadLifetimeManager
będzie współdzielić obiekty między zadaniami? Jeśli to prawda, czy istnieje inny sposób zarządzania czasem życia obiektu z jednością, który pozwoliłby każdemu zadaniu pracować w izolacji, niezależnie od wątku, na którym działa?
EDIT:
Gdy wybrana odpowiedź poniżej będzie osiągnąć to samo, skończyło się używając HierarchicalLifetimeManager
i dziecko pojemniki do osiągnięcia izolacji zależnościach dla każdego zadania.
Oto przykład:
// 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();
});
Twoja odpowiedź jest poprawna, ale chciałem tylko dodać, że skończyłem używając 'HieararchicalLiftetimeManager' i stworzyłem kontener potomny w zadaniu. Wynika to z konieczności użycia kontenera do dynamicznego rozwiązania niektórych usług z jednej z klas zadań. Wiem, że używanie kontenera jako lokalizatora usług jest zapachem kodu, ale tak to jest skonfigurowane i nie ma czasu, aby to naprawić ... – Pinetree
@Pinetree Czy była jakaś szansa, aby pokazać, jak to zrobiłeś? Dzięki – nfplee
@nfplee Nie mam kodu w domu i nie pamiętam tego z mojej strony. Opublikuję to, co zrobiłem w poniedziałek, kiedy dostanę pracę. – Pinetree