i am about to learn IoC and Dependency Injection. And i am wondering if i understood the priciple an the pattern right.
I try to implement a UnitOfWork / Repository Pattern. I want two implementations of my Repository Classes for Unit Testing, and i want the UnitOfWork to "decide" which Concrete Implementation to instantiate (with the Help of Unity).
The IUserRepository Interface
public interface IUserRepository
{
List<User> getAll();
}
The Repository Implementation using real data
public class UserRepository : IUserRepository
{
private MyDbContext db;
public UserRepository(MyDbContext db)
{
this.db = db;
}
public List<DomainModel.User> getAll()
{
return db.Users.ToList();
}
}
The FakeRepository Implementation
public class FakeUserRepository : IUserRepository
{
private List<User> userSet;
public FakeUserRepository()
{
// Fake Data
userSet = new List<User>();
userSet.Add(new User { Username = "john", Active = true, EMail = "john@ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "ashley", Active = true, EMail = "ashley@ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "kaidan", Active = true, EMail = "kaidan@ann.net", Password = "supersecret" });
userSet.Add(new User { Username = "tali", Active = true, EMail = "tali@ann.net", Password = "supersecret" });
}
public List<DomainModel.User> getAll()
{
return userSet;
}
}
My UnitOfWork Implementation using Unity
// To Keep it simple, i skipped the IDisposable part ;)
public class UnitOfWork
{
MyDbContext db;
private IUserRepository userRepository;
UnityContainer container = new UnityContainer();
public UnitOfWork(bool fake = false)
{
if (fake)
{
container.RegisterType<IUserRepository, FakeUserRepository>();
}
else
{
db = = new MyDbContext();
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(db));
}
}
public IUserRepository UserRepository
{
get
{
if (userRepository == null)
{
userRepository = container.Resolve<IUserRepository>();
}
return userRepository;
}
}
public void Save()
{
db.SaveChanges();
}
}
Now when i call new UnitOfWork()
it will give me the "UnitOfWork with RealData" Implementation. If i call new UnitOfWork(fake: true)
it will give me the "UnitOfWork with Fake Data". So far so good. But is this the way Unity and DI should be used? If my Application grows to say 30 Repositories do i end up defining large "If/else" Blocks, right? And imagine a want do add more data stores like XML or WCF as Source for Data. If i continue to use it like above, i will end up with a very complex and blown UnitOfWork Class.
First: I am not sure if i understood DI and Unity as it's ment to be used. If i understood it right: would it be better to use a Factory that gives me the right Type of UnitOfWork?
Any Help or tip is very welcome.
Thanks,
Matze
if (fake)
). Prevent doing that - Steven 2012-04-04 08:32
I would separate the Unit of Work like you did with the repositories: an IUnitOfWork interface and concrete classes for the fake and the Entity Framework Unit of Work. The Unit of Work you have now violates the Single Responsibility Principle because it has multiple responsibilities:
If you have a separate Unit of Work for Entity Framework, you won't need the container to resolve the repositories from, but you can make them member variables which you initialize in your constructor. You only have to register the correct Unit of Work on the container.