Question

I'm creating a complex service, and I ran into a little problem. Here is my situation:

ITask: these are the classes that get called by my service to execute big and long executing things.

IStep: A task can contain steps, these steps themselves execute pieces of code that can be re-used in other tasks (e.g. a "create user"-step, "create project"-step, ...)

Now, both tasks and steps need a unit of work (which contains multiple EF Contexts). These NEED to be shared inside a single task (so the same unitOfWork needs to be used in all the steps of one single task, but only in that one task). This is because of the change tracking inside EF.

So I figure I need to create something in unity, with which I can tell it that it needs to retrieve the context of a step (inside a task).

I'm currently using "ContainerControlledLifetimeManager", and this works inside a single Task, but not with multiple Tasks..

container.RegisterType<IUnitOfWork, UnitOfWork>(new ContainerControlledLifetimeManager());

The msdn says: A LifetimeManager that holds onto the instance given to it. When the ContainerControlledLifetimeManager is disposed, the instance is disposed with it.

What do I dispose? How/Where do I dispose it (I don't have a reference to the lifetimeManager?!)? How does this work with constructor injection?. Should I use property injection and use a "manager" --> container.Resolve>(task.Id)

Thanks

Was it helpful?

Solution

The trick here is to let the UnitOfWork live for the duration of a certain 'scope' and a single thread needs to be wrapped with such scope.

Registering instances in an explicit scope is done in Unity using the HierarchicalLifetimeManager and starting a new child container:

container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());

Wrapping a new child container scope around the execution of a task, can be done with a decorator:

public class HierarchicalLifetimeTaskDecorator : ITask
{
    private readonly Container container;

    public HierarchicalLifetimeTaskDecorator(Container container) {
        this.container = container;
    }

    public void Execute() {
        using (var scope = container.CreateChildContainer()) {
            ITask realTask = scope.Resolve<ITask>();
            realTask.Execute();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top