Para entender as interfaces genéricas é importante entender o conjunto de dois conceitos: generics e interfaces. Para entender com melhor profundidade esse artigo, é recomendado também o estudo do padrão repositório.
No dia a dia dos programadores é comum usarmos Interfaces para dar mais qualidade ao nosso código. Por isso, muitas vezes, quando queremos criar padrões para o nosso projeto em que várias classes devem herdar um modelo (exemplo classe de serviço e repositórios), e para evitar que tenhamos que criar múltiplas interfaces para atender ao mesmo propósito, surgem as Interfaces com tipos genéricos.
Temos uma aplicação simples que em seu primeiro momento apenas existia a necessidade de uma Entidade Conta
. Então, inicialmente a aplicação tinha sido sido feita para ter métodos CRUD (métodos padrões) e dois métodos específicos em sua interface IContaRepository
.
public interface IContaRepository
{
// CRUD
IEnumerable<ContaModel> GetAll();
ContaModel GetById(int id);
ContaModel Update(ContaModel conta);
ContaModel Insert(ContaModel conta);
bool Delete(ContaModel conta);
// métodos específicos
IEnumerable<ContaModel> GetByName(string name);
ContaModel GetByEmail(string email);
}
Tudo ocorreu como o planejado até que depois de duas semanas surgiu a demanda de acrescentar duas novas Entidades. Assim, se eu criasse uma nova classe, teria que colocar todos os métodos “GetAll, GetById, Update, Insert e Delete” gerando um trabalho maior e repetitivo.
Por isso, para facilitar a vida e criar um padrão, vamos gerar uma interface genérica.
Para definir essa interface vamos construir da mesma forma a nossa interface, apenas vamos mudar alguns detalhes para que fique de acordo com uma interface genérica.
where T : class
public interface IBaseRepository<T> where T : class
{
IEnumerable<T> GetAll();
T GetById(int id);
T Update(T model);
T Insert(T model);
bool Delete (T model);
}
E a partir desse momento, toda interface que usará métodos de CRUD deverá herdar a interface IBaseRepository
e assim os métodos genéricos serão extendidos.
public interface IContaRepository : IBaseRepository<ContaModel>
{
IEnumerable<ContaModel> GetByName(string name);
ContaModel GetByEmail(string email);
}
Preste atenção que o modelo ContaModel
está dentro do parâmetro do IBaseRepository
, fazendo com que os métodos herdados sejam baseados nesse modelo.