开发者

Dependency Injection and Generic Collections

开发者 https://www.devze.com 2022-12-10 21:39 出处:网络
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'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();
    IEnumera开发者_开发问答ble<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.


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.


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;
    }
}


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号