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.

Exemplo aplicado

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.

Definindo 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.

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.

Padrão Repository