4

I don't know if the following is weird but actually need an interface for an interface< T > in order to store it in a List without specify a specific implementation.

Example:

public interface IRepository<T>
{
    void Add(T newEntity);
    void Remove(T entity);
    IEnumerable<T> FindAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}

public interface IUnitOfWork
{
    //Here i would like to store just a IRepository without implementation
    IList<IRepository<**I have to specify implementation here**>> Repositories { get; set; }
    bool Commit();
}

You are free to suggest me better ways to do that. This is only what i have though to do...

Thanks

EDIT

I cannot provide a non-generic interface because i'm using it like this:

public class GenericRepository<T> : IRepository<T>
{
    ...generic repository methods...
}

//Specific repository...
public class MyTableClassRepository<MyTable> : GenericRepository<MyTable>
{
    public MyTableClassRepository(Database context) : base(context)
    {
    }
}
CodeArtist
  • 5,534
  • 8
  • 40
  • 65
  • 1
    Provide a non-generic interface, it's much easier than dealing with [open generics](http://stackoverflow.com/questions/2173107/what-exactly-is-an-open-generic-type-in-net). Although you'd likely be better off just having `IRepository Foos { get; }` ... `IRepository Bars { get; }` on your `IUnitOfWork`. If you really want to avoid writing that boilerplate code you could consider getting rid of the `Repositories` property and instead using something like Ninject to `Bind(typeof(IRepo<>)).To(typeof(Repo<>))` and injecting `IRepo` wherever you need it. – ta.speot.is Jul 25 '14 at 02:34
  • 3
    Also consider whether you want to return `IEnumerable` or `IQueryable` on your repository. The latter will allow you to skip/take/order at the database rather than in-memory – ta.speot.is Jul 25 '14 at 02:41
  • 2
    I'm not sure why you say you can't provide a non-generic interface. `public interface IRepository : IRepository`. Then `GenericRepository` implements the `IRepository` methods too (except in terms of `object` instead of `T`). EF's context has non-generic methods you can delegate most of your implementation to. – ta.speot.is Jul 25 '14 at 02:43
  • 2
    Consider as an **anology** `List: IEnumerable, IEnumerable` implements both a generic and non-generic interface. Is there something that stops you from doing `GenericRepository : IRepository, IRepository` ? – AaronLS Jul 25 '14 at 02:54

1 Answers1

3

Consider the following design

public interface IUnitOfWork : IDisposable
{
    T GetRepository<T>() where T : class;
    void SaveChanges();
}

In the implementation of the UnitOfWork you can use IoC container (Autofac in the example below)

public class UnitOfWork : IUnitOfWork
{
    private static IContainer _container;
    Hashtable _repositories = new Hashtable();
    public static Module CurrentRepositoriesModule { get; set; }

    public UnitOfWork()
    {
        var builder = new ContainerBuilder();
        if (CurrentRepositoriesModule != null)
            builder.RegisterModule(CurrentRepositoriesModule);
        _container = builder.Build();
    }

    public T GetRepository<T>() where T : class
    {
        var targetType = typeof(T);
        if (!_repositories.ContainsKey(targetType))
        {
            _repositories.Add(targetType, _container.Resolve<T>());
        }
        return (T)_repositories[targetType];
    }

    public void SaveChanges()
    {
        throw new NotImplementedException();
    }

}
eternity
  • 1,668
  • 15
  • 25