简体   繁体   中英

Base class with a generic type which implements an interface with a generic type

I'm implementing a Repository pattern and I would like to FooRepository to be re-usable for all models that implement IEntity however the IDE (Rider) says that Type parameter 'IEntity' hides interface 'IEntity' and later one causes the error message Cannot resolve symbol 'ID' in the GetById method.

What is the proper way to create a base class for generic types ( IEntity in this case) that also implements an interface which takes the same generic class?

The end goal is to re-use the FooRepository for other models (than Bar ) as the methods such as GetById as they will mostly function the same between them.

public abstract class FooRepository<IEntity> : IRepository<IEntity>
{
    private List<IEntity> _data;

    public List<IEntity> GetAll()
    {
        return this._data;
    }

    public IEntity GetById(int id)
    {

        return this.GetAll().Single(c => c.ID == id);
    }
}

public class BarRepository : FooRepository<Bar>
{
}

public interface IEntity
{
    int ID { get; set; }
}

public interface IRepository<IEntity>
{
    List<IEntity> GetAll();
    IEntity GetById(int id);
}

public class Bar : IEntity
{
    public int ID { get; set; }
    public string Name { get; set; }
}

I fixed your abstract class by using generics.

public abstract class FooRepository<T> : IRepository<T> where T: IEntity
    {
        private List<T> _data;

        public List<T> GetAll()
        {
            return this._data;
        }

        T IRepository<T>.GetById(int id)
        {
            return this.GetAll().Single(c => c.ID == id);
        }
    }

    public class BarRepository : FooRepository<Bar>
    {
    }

    public interface IEntity
    {
        int ID { get; set; }
    }

    public interface IRepository<T>
    {
        List<T> GetAll();
        T GetById(int id);
    }

    public class Bar : IEntity
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

I do think a nicer (less complicated) solution is:

public abstract class FooRepository<T> where T: IEntity
    {
        private List<T> _data;

        public List<T> GetAll()
        {
            return this._data;
        }

        T GetById(int id)
        {
            return this.GetAll().Single(c => c.ID == id);
        }
    }

    public class BarRepository : FooRepository<Bar>
    {
    }

    public interface IEntity
    {
        int ID { get; set; }
    }


    public class Bar : IEntity
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

You do not need the IRepository interface because your abstract class is covering this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM