Ed S
Ed S

Reputation: 140

Injecting a class instance to a generic interface

I have this model class:

public class FunctieModel: ObservableObject
{ ... }

The base interface for repositories:

public interface IBaseRepo<T> where T : ObservableObject
{
    void Delete(int id);
    T GetItem(int id);
    IEnumerable<T> GetList();
    bool Update(T model);
    bool Insert(T model);
}

The specific interface for repository of type FunctieModel

public interface IFunctieRepo : IBaseRepo<FunctieModel>
{}

The implementation of the repository for my FunctieModels:

public class FunctieRepoSql : IFunctieRepo
{...}

My tester class that must be able to work with the repositories, which must be injected:

public class Tester    
{
    IBaseRepo<ObservableObject> repo;

    public Tester(IBaseRepo<ObservableObject> repo)
    {
        this.repo = repo;
    }
}

This all compiles fine. Now I need to instantiate the tester class with different repositories.

new Tester(new FunctieRepoSql())

This is where my problem is. The error is
cannot convert from FunctieRepoSql to IBaseRepo<ObservableObject>

I am obviously missing something. Anyone have a clue how I can get this to work?

Upvotes: 1

Views: 103

Answers (2)

Kirk Woll
Kirk Woll

Reputation: 77546

You have two key options to consider. The easiest is to simply make Tester generic and consume a type parameter that you can pass to IBaseRepo<T>.

public class Tester<T> where T : ObservableObject
{
    IBaseRepo<T> repo;

    public Tester(IBaseRepo<T> repo)
    {
        this.repo = repo;
    }
}

Then you can change your calling code to:

new Tester<FunctieModel>(new FunctieRepoSql())

If for whatever reason you cannot use this technique, you could instead create another non-generic interface, IBaseRepo that IBaseRepo<T> extends. It should surface equivalent methods as IBaseRepo<T> (for those methods that utilize T) but instead declare them without the use of that type argument. This is analogous to IEnumerable and IEnumerable<T>. Having done this, you could then make Tester accept an IBaseRepo in its constructor rather than the generic version.

Upvotes: 0

Nadia Chibrikova
Nadia Chibrikova

Reputation: 5036

You can't convert IBaseRepo<FunctieModel> to IBaseRepo<ObservableObject>. For example imagine a generic collection of lets say cats, if you convert it to a collection of animals you'll be able to add a dog to it, which is undesirable. However, you can use out keyword here:

public interface IBaseRepo<out T> where T : ObservableObject

But then you won't be able to accept ObservableObjects as input (msdn about out).

Upvotes: 1

Related Questions