Instantiate IUnitOfWork for each ViewModels in WPF/Prism app using Unity

Aug 12, 2012 at 8:56 AM

I have lots of repositories like this:

public class PersonRepository : IPersonRepository
{
   
private readonly IUnitOfWork _unitOfWork;

   
public PersonRepository(IUnitOfWork instance)
   
{
        _unitOfWork
= instance;
   
}

   
//Remove, Get methods...
   
public void Add(Person p)
   
{
        _unitOfWork
.Context.People.Add(p);
   
}
}

and Unit of work class like this:

public class UnitOfWork : IUnitOfWork, IDisposable
{
   
public UnitOfWork(){ }

   
private readonly HezarehContext _context = new HezarehContext();
   
public HezarehContext Context
   
{
       
get
       
{
           
return _context;
       
}
   
}

   
public int Save()
   
{
       
return _context.SaveChanges();
   
}

   
public void Initialize()
   
{
       
Context.Database.Initialize(false);
   
}

   
#region IDisposable Members

   
public void Dispose()
   
{
        _context
.Dispose();
   
}

   
#endregion
}

Now i want each time my ViewModels gets resolved, a new IUnitOfWork instantiated. Most of my ViewModels are like this:

public class PeopleMainViewModel : NotificationObject
{
   
// both of repositories must have same instance of IUnitOfWork
   
private readonly IPersonRepository _personRepository = ServiceLocator.Current.GetService<IPersonRepository>();
   
private readonly ICategoryRepository _categoryRepository = ServiceLocator.Current.GetService<ICategoryRepository>();

   
public PeopleMainViewModel()
   
{
       
InitializeView();
   
}

   
// add, edit, remove commands ...
}

ViewModels always gets resolved using Unity Container like this:

Container.RegisterType<IPersonRepository, PersonRepository>();
// resolve in InjectionProperty...
Container.RegisterType<Object, PeopleMainView>("PeopleMainView", new InjectionProperty(PeopleMainView.DataContextProperty.Name, Container.Resolve<PeopleMainViewModel>();

And my question is, How and Where i Register my ViewModels and IUnitOfWork to haveIUnitOfWork instance for each of them?

Aug 14, 2012 at 2:02 AM
Edited Aug 14, 2012 at 3:24 AM

I see by this question that you've arrived at a solution.  In the posted approach the IUnitOfWork instance is injected into the ViewModel and the IUnitOfWork is passed as an argument to Resolve.  I'll post it here for completeness:

public class PeopleMainViewModel : NotificationObject
{
    private readonly IPersonRepository _personRepository = null;
    private readonly ICategoryRepository _categoryRepository = null;

    public PeopleMainViewModel(IUnityContainer container, IUnitOfWork unitOfWork)
    {
        // now both of repositories have same instance of IUnitOfWork
        _personRepository = container.Resolve<IPersonRepository>(new ParameterOverride("unitOfWork", unitOfWork));
        _categoryRepository = container.Resolve<ICategoryRepository>(new ParameterOverride("unitOfWork", unitOfWork));
        InitializeView();
    }

    // add, edit, remove commands ...
}

This will work (as you know since you posted it!).  Another approach would be to register IUnitOfWork with a PerResolveLifetimeManager.  The PerResolveLifetimeManager behaves "like a TransientLifetimeManager, but also provides a signal to the default build plan, marking the type so that instances are reused across the build-up object graph".

So you could register the IUnitOfWork with the container:

 

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

Then you could modify the ViewModel design to accept the repositories in the constructor:

public class PeopleMainViewModel : NotificationObject
{
    private readonly IPersonRepository _personRepository;
    private readonly ICategoryRepository _categoryRepository;

    public PeopleMainViewModel(IPersonRepository personRepository, ICategoryRepository categoryRepository)
    {
        // now both of repositories have same instance of IUnitOfWork
        _personRepository = personRepository;
        _categoryRepository = categoryRepository;          
        InitializeView();
    }

    // add, edit, remove commands ...
}

Now when the PeopleMainViewModel is resolved from the container the same UnitOfWork instance will be used for all objects resolved in the PeopleMainViewModel object graph.  

The benefit of this approach is that the ViewModel doesn't have any knowledge of the (Unity) container.  Also, in terms of understanding the application design the dependencies of the ViewModel are easy to see since they are in the constructor.

I'll also add that if you need more control of object lifetime you could go with a HierarchicalLifetimemanager combined with a child container.  In that way your chosen object would be a singleton for the lifetime of the child container.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com