kevin c
kevin c

Reputation: 805

How do I make a method return a generic method?

I am creating a repository as follows:

public class StagingRepository
{
    private IRepository<CurrentTransformer> CurrentTransformerRepository { get; set; }
    private IRepository<Equipment> EquipmentRepository { get; set; }
    private IRepository<Line> LineRepository { get; set; }
    public StagingRepository()
    {
        this.CurrentTransformerRepository = new Repository<CurrentTransformer>();
        this.EquipmentRepository = new Repository<Equipment>();
        this.LineRepository = new Repository<Line>();
    }
}

All this works... however what I am trying to add is a method within the class that returns one of the Repositories above based on a string value.

public IRepository<Object> SetRepo(string TableName)
{
    switch (TableName)
    {
        case "Line":
            return LineRepository;
            break;
    }
}

I know the above does not work but it gives you an idea of what I am trying to accomplish. My goal would be I should be able to setup something like this in my code to call the repository:

StagingRepository _repo = new StagingRepository();
var myList = _repo.SetRepo("Line").All(); //All is a function of IRepository

Any Help would be greatly appreciated.

Upvotes: 2

Views: 88

Answers (1)

BartoszKP
BartoszKP

Reputation: 35921

You can make IRepository covariant:

public interface IRepository<out T>

This way, you can always use IRepository<Derived> in place of IRepository<Base> when returning from a method. In your case, your code will now compile and work:

public IRepository<object> SetRepo(string TableName)
{
    switch (TableName)
    {
        case "Line":
            return LineRepository;
            break;
    }
}

because Line is derived from object, so you can return IRepository<Line> for IRepository<object>.

This however won't work if you use T as an argument - type can not be both covariant and contravariant. In such case, consider moving non-generic methods from IRepository<T> to a non-generic version IRepository and make your repositories implement both. This way you could have:

public IRepository SetRepo(string TableName)
// ...

By the way, the name SetRepo is misleading - the function doesn't set anything, it rather "gets" an appropriate repository.

Upvotes: 3

Related Questions