Базовый класс с универсальным типом, который реализует интерфейс с универсальным типом - PullRequest
0 голосов
/ 06 января 2019

Я реализую шаблон репозитория, и я хотел бы, чтобы FooRepository можно было повторно использовать для всех моделей, которые реализуют IEntity, однако IDE (Rider) сообщает, что Type parameter 'IEntity' hides interface 'IEntity' и более поздние версии вызывают сообщение об ошибке Cannot resolve symbol 'ID' в методе GetById.

Как правильно создать базовый класс для универсальных типов (в данном случае IEntity), который также реализует интерфейс, который принимает тот же универсальный класс?

Конечная цель состоит в том, чтобы повторно использовать FooRepository для других моделей (кроме Bar) в качестве методов, таких как GetById, поскольку они в основном будут функционировать одинаково между ними.

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

1 Ответ

0 голосов
/ 06 января 2019

Я исправил ваш абстрактный класс с помощью обобщений.

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

Я думаю, что более хорошее (менее сложное) решение:

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

Вам не нужен интерфейс IRepository, потому что ваш абстрактный класс покрывает это.

...