Реализация интерфейсов C#

Я не знаю, как правильно управлять интерфейсами в C#. Моя цель - создать абстрактный класс для моих сервисов Business Layer, которые имеют некоторые общие методы (такие как Save(), Dispose()), которые вызывают различные методы репозитория DAL. Я хочу избежать повторения во всех моих службах что-то вроде:

public Save() 
{
   repository.Save();
}

У меня есть сценарий, похожий на это:

Интерфейс

namespace Common
{
    public interface IRepository
    {
        void Save;
        void Dispose;
    }
}

DAL

namespace DAL
{
    public Repository : IRepository
    {
        public void Save() {};
        public void Dispose() {};
        public void Add() {}
    }
}

BL

namespace BL
{
    public abstrac BaseService
    {
        protected IRepository repository;
        protected BaseService(IRepository repo)
        {
            repository = repo;
        }

        public Save() 
        {
            repository.Save();
        }
    }

    //...

    //Tentative 1
    public Service : BaseService
    {
        private Repository rep;

        public Service()
            : base(new DAL.Repository())
        {
            rep = base.repository; // ERROR: cannot convert IRepository to Repository
        }
    }
}

Я пробовал также это:

//Tentative 2
public Service : BaseService
{
    private IRepository rep;

    public Service()
        : base(new DAL.Repository())
    {
        rep = base.repository; // OK
    }

    public void Add()
    {
        rep.Add() // ERROR: IRepository doesn't contain a definition for 'Add'
    }
}

Я знаю, что могу определить в интерфейсе все методы, которые я хочу использовать, но мне придется решать множество проблем с универсальными типами, и, как вы должны понять из моего вопроса, я довольно нов в C# и Я хочу избежать сложности, это возможно, пока я буду, по крайней мере, более опытным:)

3 ответа

Решение
public Service()
        : base(new DAL.Repository())
    {
           rep = (Repository)base.repository;

    }

Таким образом, вы получите сервис Add(), который не является частью IRepository, а является более новой реализацией в расширенном классе.

Во-первых, я думаю, что у вас есть конфликт имени с вашим участником IRepository rep.

Попробуйте использовать DAL.IRepository rep

Причина, по которой вы получаете ошибку, состоит в том, что вы определили "Добавить" как нечто уникальное для "Репозитория". Ваша переменная-член - это "IRepository", позволяющая вам поместить на нее все, что реализует "IRepository".

То, что вы МОЖЕТЕ поместить в него репозиторий, не означает, что все на нем будет репозиторием. (Подумайте, как хорошо выглядят пальцы и пальцы, все пальцы - это пальцы, но не все пальцы - большие пальцы)

Если вам нужно вызвать add в любом репозитории, то добавьте его в интерфейс. Иначе, вам нужно решить, должен ли этот участник быть IRepository или Repository.

Кроме того, вы могли бы использовать

    Repository myRep = rep as Repository;
    if(rep!=null)
    {
       myRep.Add();
       ...
       profit();
    }

Видя, что вашей главной проблемой является отсутствие доступа к Add метод, и, поскольку в любом случае это относительно общий метод, я бы сначала рекомендовал добавить его к вашему IRepositoryтак это выглядит так:

public interface IRepository
{
    void Add();
    void Save();
    void Dispose();
}

Затем вы реализуете свои соответствующие репозитории, наследуя от IRepository, Теперь, понятно, вы можете иметь возможность доступа к пользовательским методам на Repository, Чтобы решить эту проблему, у вас есть BaseService принять общий репозиторий:

public BaseService<T> where T : IRepository
{
    protected T repository { get; set; }
    protected BaseService(T repo)
    {
        repository = repo;
    }
}

Тогда сервис будет выглядеть так

public UserService : BaseService<UserRepository>
{
    public UserService() : base(new DAL.UserRepository())
    {
        // base.Repository is now a UserRepository.
    }    
}

С этой реализацией ваш UserService сможет получить доступ ко всем методам, которые UserRepository разоблачает, так как он строго напечатан с универсальным. Надеюсь это поможет.

Другие вопросы по тегам