Реализация интерфейсов 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
разоблачает, так как он строго напечатан с универсальным. Надеюсь это поможет.