views:

185

answers:

3

I'm going round in circles at the moment trying to get the pattern right for using Dependency Injection with a number of IEnumerables.

I have three types of object that I want to return from my database: Projects, Batches and Tasks. I want to create a Repository that has the following form:

public interface IRepository<T>
{
    IEnumerable<T> GetAll();
    IEnumerable<T> GetAllActive();
    IEnumerable<T> GetItemsByUserName(string UserName);
    T GetItemById(int ID);
}

So when I create a concrete implementation of a ProjectRepository, it will look like this:

IEnumerable<Project> GetAll();
IEnumerable<Project> GetAllActive();
IEnumerable<Project> GetItemsByUserName(string UserName);
Project GetItemById(int ID);

And similarly for Tasks:

IEnumerable<Task> GetAll();
IEnumerable<Task> GetAllActive();
IEnumerable<Task> GetItemsByUserName(string UserName);
Task GetItemById(int ID);

My difficulty is in trying to declare an IRepository in my calling code. When I declare the reference, I find myself needing to declare a type:

private IRepository<Project> Repository;

...which is of course pointless. I'm going wrong somewhere but can't get my head around it at the moment. How do I use dependency injection so that I can declare an interface that makes use of all three concrete types?

Hope I've explained myself properly.

+4  A: 

Use generics:

public class YourClass<T>
{
    public YourClass(IRepository<T> repository)
    {
        var all = repository.GetAll();
    }
}

Of course, at some point you need to provide T, which might look like this:

var projectClass = yourDIContainer.Resolve<YourClass<Project>>;

In terms of registering your types with your DI container, it may be useful if your DI container supports open generics. For example, check out this post that shows how Unity supports this.

HTH,
Kent

Kent Boogaart
A: 

Hope this might help you in the way you want to make the code.

public class Repository : IRepository<Repository>
{

    public Repository()
    {
    }

    #region IRepository<Repository> Members

    public IEnumerable<Repository> GetAll()
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public IEnumerable<Repository> GetAllActive()
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public IEnumerable<Repository> GetItemsByUserName(string UserName)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    public Repository GetItemById(int ID)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    #endregion
}



public class RepositoryCreator<T> where T : IRepository<T>
{
    public IRepository<Repository> getRepository()
    {
        Repository r = new Repository();
        return r;
    }


    public IRepository<Blah> getBlah()
    {
        Blah r = new Blah();
        return r;
    }
}
Beginner
A: 

Given that you've defined the repository interface as returning a specific type, why do you think it's pointless to give the type you're expecting it to return in client code?

It's only pointless if you don't care the return type,but then the whole generic interface design is pointless.

If you want a repository object to only work with the specified type, then you will need three objects (or possibly an object with three interfaces, depending on implementation language) to provide your project repository, batch repository and task repository.

Pete Kirkham