Suponha que eu defino duas interfaces abaixo:
public interface IReader
{
void Read(string bookName);
}
public interface IWriter
{
void Write(string bookName);
}
Agora quero implementar a interface do IReader assim:
public class Reader : IReader
{
private IEnumerable<string> _books;
public Reader(IEnumerable<string> books)
{
_books = books; // List of books is given through constructor
}
public void Read(string bookName)
{
if (_books.Contains(bookName))
{
// Reading here
}
else
{
throw new InvalidOperationException("Given book name was not found in the library.");
}
}
}
E agora eu quero definir uma classe de nível mais alto que implemente as duas interfaces:
public class Person : IReader, IWriter
{
// This is the data I want to share with IReader argument of constructor
private IList<string> _books = new List<string>();
private IReader _reader;
public Person(IReader reader)
{
_reader = reader; // How do I share books with this object?
}
public void Read(string bookName)
{
_reader.Read(bookName);
}
public void Write(string bookName)
{
_books.Add(bookName);
}
}
Como você percebeu, usei a composição para implementar a interface do IReader. Eu preciso injetar uma instância do Reader na classe Person, mas também preciso compartilhar os dados dos livros da minha pessoa com a instância do Reader. Este é o problema que quero resolver.
Até agora, não fornecemos uma maneira de compartilhar a lista de livros com a interface do IReader. Algumas opções vêm à minha mente:
Primeira opção: Crie uma interface IReaderFactory e sua implementação, que cria uma instância como esta:
public interface IReaderFactory
{
IReader Create(IEnumerable<string> books);
}
public class ReaderFactory : IReaderFactory
{
public IReader Create(IEnumerable<string> books)
{
return new Reader(books);
}
}
Tudo isso é bom, agora posso injetar o IReaderFactory no meu construtor Person em vez de no IReader. A desvantagem é que requer 2 definições adicionais IReaderFactory e ReaderFactory.
Segunda opção: Adicione outro método à interface do IReader assim:
void Initialize(IEnumreable<string> books);
Isso também funciona, no construtor da pessoa eu posso chamar esse método e passar meus livros para ele. Mas não parece elegante para mim, porque agora eu tenho que lembrar de chamar esse método, e esse método pode ser chamado muitas vezes , o que é algo que não fazemos quer.
Eu não quero usar um contêiner DI e resolver uma instância do IReader dentro do construtor do Person, porque ele oculta as dependências da classe Person.
Agora, qual é a melhor maneira de entrar nesse tipo de situação sem violar o Princípio de Inversão de Dependência ?