Generic factory with repositories: Part 2
By Rob Jones | May 18, 2010
This post is part of a series:
- Generic factory and repositories: Part 2 revisited
- Generic factory and repositories: Part 2
- Generic factory and repositories: Part 1
- WCSF, Repositories and Unit of Work?
Yesterday I posted my musings on using the factory pattern to instantiate my repositories without needing to have a reference to the actual repository class, but only the interface. This morning I made some progress and I have actually managed to create some working code. Some of the code, especially the SimpleRepositoryFactory, can do with a little refinement. However, the basic principle seems to be working and that is all that matters at the moment.
The Repositories
Let’s start with the beginning and have a look at how I defined my repository classes and interfaces.
public interface IRepository<T> where T : class
{
IQueryable<T> AsQueryable();
IEnumerable<T> GetAll(string[] includes = null);
IEnumerable<T> GetMany(Expression<Func<T, bool>> where,
string[] includes = null);
T GetSingle(Expression<Func<T, bool>> where,
string[] includes = null);
T GetFirst(Expression<Func<T, bool>> where,
string[] includes = null);
void Delete(T entity);
void Add(T entity);
}
public abstract class Repository<T> : IRepository<T>
where T : class
{
private IUnitOfWork unitOfWork;
public Repository(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
#region IRepository members
// For the sake of simplicity, I'll leave the implementation
// of the IRepository interface away. I might put up a source
// code zip package later!
#endregion
}
Now that I have the crude basics for a repository, it’s time to put them to work.
The following code demonstrates how to declare a repository that uses the IRepository interface and the abstract Repository base class. Because the IUserRepository interface implements the IRepository interface, I will be able to call all methods declared in IRepository by talking to my IUserRepository. This is pretty neat, since I won’t ever need to know anything about the concrete implementations when I start implementing the code in my (web) application.
public interface IUserRepository : IRepository<User>
{
}
public class UserRepository : Repository<User>, IUserRepository
{
public UserService(IUnitOfWork unitOfWork)
: base(unitOfWork)
{
}
}
The generic factory
Now that I’ve shown you the basics of my repository, I will show you the implementation of my SimpleRepositoryFactory. Mind you, it’s nothing special and it’s exactly what the name suggests; simple.
public static class SimpleRepositoryFactory
{
public static T Create<T>(params object[] args)
{
if (typeof(T) == typeof(IUserService))
{
// Excuse me for the code mark-up here!
return (T)InternalRepositoryFactory<IUserService,
UserService>.Create(args);
}
else
{
return default(T);
}
}
}
The downside of using this approach is that I will have to edit the SimpleRepositoryFactory with every new repository class I might add. A little inconvenient, but for now it suits me fine as I will only need to add it in the Create() method of the factory by using another else-if statement. You might notice that this class calls InternalRepositoryFactory to actually instantiate the object.
The InternalRepositoryFactory is actually a very generic object factory. It will be able to create any object, as long as the object implements the specified interface.
internal static class InternalRepositoryFactory<I, C> where C : I
{
internal static I Create(params object[] args)
{
return (I)Activator.CreateInstance(typeof(C), args);
}
}
Using the factory!
Now that I’ve got all the pieces of the puzzle, it’s time to start putting it all together. Notice how I will still be able to use my repositories and unit of work as I described here! Not only that, but I’m also using interfaces instead of instantiating concrete implementations of my repositories!
using (TransactionScope ts = new TransactionScope())
{
using (IUnitOfWork uof = new ConcreteUnitOfWork())
{
// Get reference to UserRepository.
IUserRepository ur =
SimpleRepositoryFactory.Create<IUserRepository>(uof);
// Get all users.
List<User> users = ur.GetAll().ToList();
// You can create more repositories here and
// do additional work using this unit of work
// and transaction scope!
// We're done!
uof.Commit();
ts.Complete();
}
}
Conclusion
I’m not really sure if this approach is correct, but for now I have solved the problem that I posted about yesterday in Part 1. This solution will allow me to create different modules and have interaction between them by only using their interfaces without needing to instantiate concrete implementations that would make my code too tightly coupled. I’m not quite happy with the implementation of SimpleRepositoryFactory and I will continue to look for a more elegant solution.




3 Comments
Pingback: Generic factory and repositories: Part 2 revisited | Storm in a Jar
Pingback: WCSF, Repositories and Unit of Work? | Storm in a Jar
Pingback: Generic factory and repositories: Part 2 revisited | Storm in a Jar