##EDIT:##
###IProvider.cs###
internal interface IProvider {
MyContext DbContext { get; set; }
IRepository<T> GetGenericRepository<T>()
where T : class;
T GetCustomRepository<T>(Func<MyContext, object> factory = null)
where T : class;
}
###Provider.cs###
internal class Provider : IProvider {
private readonly Factory _factory;
protected Dictionary<Type, object> Repositories { get; private set; }
public MyContext DbContext { get; set; }
internal Provider() {
_factory = new Factory();
Repositories = new Dictionary<Type, object>(); }
protected virtual T MakeRepository<T>(
Func<MyContext, object> factory, MyContext dbContext) {
var f = factory ?? _factory.GetRepositoryFactory<T>();
if (f == null) throw new NotSupportedException(typeof(T).FullName);
var repo = (T)f(dbContext);
Repositories[typeof(T)] = repo;
return repo; }
public IRepository<T> GetGenericRepository<T>() where T : class {
return GetCustomRepository<IRepository<T>>(
_factory.GetRepositoryFactoryForEntityType<T>()); }
public virtual T GetCustomRepository<T>(Func<MyContext, object> factory = null)
where T : class {
object repoObj;
Repositories.TryGetValue(typeof(T), out repoObj);
if (repoObj != null) { return (T)repoObj; }
return MakeRepository<T>(factory, DbContext); }
public void SetRepository<T>(T repository) {
Repositories[typeof(T)] = repository; }
}
###Factory.cs###
internal class Factory {
private readonly IDictionary<Type, Func<MyContext, object>> _factories;
public Factory() { _factories = GetFactories(); }
public Factory(IDictionary<Type, Func<MyContext, object>> factories) {
_factories = factories; }
private IDictionary<Type, Func<MyContext, object>> GetFactories() {
return new Dictionary<Type, Func<MyContext, object>>
{ { typeof(ILogRepository),
context => new LogRepository(context) },
{ typeof(IExtendedRepository),
context => new ExtendedRepository(context) } }; }
protected virtual Func<MyContext, object> DefaultEntityRepositoryFactory<T>()
where T : class {
return dbContext => new Repository<T>(dbContext); }
public Func<MyContext, object> GetRepositoryFactory<T>() {
Func<MyContext, object> factory;
_factories.TryGetValue(typeof(T), out factory);
return factory; }
public Func<MyContext, object> GetRepositoryFactoryForEntityType<T>()
where T : class {
return GetRepositoryFactory<T>() ?? DefaultEntityRepositoryFactory<T>(); } }
###IRepository.cs###
public interface IRepository<T> : IDisposable
where T : class
{
IList<T> All();
IList<T> Find(Func<T, bool> f);
T Add(T t);
T Update(T t);
T Remove(T t);
}
###Repository.cs###
internal class Repository<T> : IRepository<T> where T : class
{
internal MyContext Context;
public Repository(MyContext context) { Context = context; }
public IList<T> All() { return Context.Set<T>().ToList(); }
public IList<T> Find(Func<T, bool> f) {
return Context.Set<T>().Where(f).ToList();
}
public T Add(T t) { /* add but don't save */ }
public T Update(T t) { /* update but don't save */ }
public T Remove(T t) { /* remove but don't save */ }
public void Dispose() { /* dispose context */ }
}
###ILogRepository.cs###
public interface ILogRepository : IDisposable
{
IList<Log> All();
IList<Log> Find(Func<Log, bool> f);
}
###LogRepository.cs###
internal class LogRepository : ILogRepository
{
internal DepofisContext Context;
public LogRepository(DepofisContext context)
{
Context = context;
}
public IList<Log> All()
{
return Context.Logs.ToList();
}
public IList<Log> Find(Func<Log, bool> f)
{
return Context.Logs.Where(f).ToList();
}
public void Dispose()
{
Context.Dispose();
}
}
###IExtendedRepository.cs###
public interface IExtendedRepository : IRepository<Extend>
{
Extend NewMethod(Extend t);
}
###ExtendedRepository.cs###
internal class ExtendedRepository : Repository<Extend>
{
public ExtendedRepository(MyContext context)
: base(context) { }
public Extend NewMethod(Extend t)
{
return t;
}
}
###IUnitOfWork.cs###
internal interface IUnitOfWork : IDisposable
{
int Save();
}
###UnitOfWork.cs###
public class UnitOfWork : IUnitOfWork
{
private MyContext Context { get; set; }
internal IProvider Provider { get; set; }
private IRepository<T> GetGenericRepository<T>() where T : class {
return Provider.GetGenericRepository<T>();
}
private T GetCustomRepository<T>() where T : class {
return Provider.GetCustomRepository<T>();
}
private void CreateContext() { Context = new MyContext(); }
public UnitOfWork() {
CreateContext();
if (Provider == null) Provider = new Provider();
Provider.DbContext = Context;
}
public IRepository<User> Users {
get { return GetGenericRepository<User>(); } }
public IRepository<Role> Roles {
get { return GetGenericRepository<Role>(); } }
public ILogRepository Logs {
get { return GetCustomRepository<ILogRepository>(); } }
public IExtendedRepository Extends {
get { return GetCustomRepository<IExtendedRepository>(); } }
public int Save() { return Context.SaveChanges(); }
public void Dispose() { /* dispose context */ }
}
As for the usage:
using(var uow = new UnitOfWork()) {
var users = uow.Users.All();
// do magic stuff here ;)
uow.Save(); // don't forget to save
}
Now the uow have these methods:
- uow.Users
- .All()
- .Find(q=>q.UserId == 1)
- .Add(new User())
- .Update(user)
- .Remove(user)
- uow.Logs
- .All()
- .Find(q=>q.LogId == 1)
- uow.Extends
- Same methods as uow.Users
- .NewMethod(extend)