So you want to create a unit of work for each form. I'm not going into whether that is a sensible choice or not.
There's several ways to achieve this:
1 - manual management
var unitOfWork = IResolutionRoot.Get<IUnitOfWork>();
IResolutionRoot.Get<Form1Presenter>(new ConstructorArgument("unitOfWork", unitOfWork, true);
Here you have ninject create a unit of work, then request a form and put the unitOfWork as ConstructorArgument on the request. The form and all it's dependencies which use the unitOfWork need to have a constructor parameter IUnitOfWork unitOfWork
. The name needs to be same as specified in the constructor argument.
So this is quite a lot of work and does not make use of all the sweetnees an IoC can provide. So i would not recommend using this approach.
2 Named Scope
Have a look at Ninject Named Scope Extension. Create the bindings as follows:
const string UnitOfWorkScopeName = "UnitOfWorkScopeName";
IBindingRoot.Bind<IUnitOfWork>().To<UnitOfWork>()
.InNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form1Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form2Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
IBindingRoot.Bind<Form3Presenter>().ToSelf()
.DefinesNamedScope(UnitOfWorkScopeName);
This will result in all the object bound with DefinesNamedScope
and all it's dependencies getting the same instance of IUnitOfWork
.
However, you can never instanciate an IUnitOfWork
when you are not in the correct scope. Thus all your forms need to define a (the same) scope. Also, a form may not depend on another form, because then you would have scope overlap.
3 Call Scope
InCallScope()
means that all objects created by one IResolutionRoot.Get() will receive the same object.
IBindingRoot.Bind<IUnitOfWork>().To<UnitOfWork>()
.InCallScope();
The bindings of all other components does not need to be adjusted.
This does not work in case you are instanciating multiple forms by one call to IResolutionRoot.Get()
Of course there's even more ways how you can manage the lifetime of a unit of work.
We have decoupled session management from IUnitOfWork and use a ThreadLocal
to determine whether we need to start a new session/transaction or use an existing one.