{tecnologia, conceitos, negócios, idéias, práticas, .NET, ruby, osx, ios e algo mais}
21/12/2009
Hoje vamos falar um pouco sobre Injeção de Dependências no C#. Injeção de Dependência é uma das formas de obter/realizar Inversão de Controle. O nome já diz quase tudo, quando uma classe possui dependência de alguma outra classe concreta, devemos então criar uma dependência para uma interface, ou seja, uma abstração.Com nossa classe dependendo de uma abstração, nós injetamos um objeto concreto nela.
Este é um conceito bastante simples, vamos entender com um pouco de código. A classe abaixo é uma classe de acesso ao banco de dados. Ela é responsável por executar um comando SQL apenas:
1 public class SqlClass{
2 public void ExecutarComando(string comando) {
3 try {
4 using (SqlConnection conexao = new SqlConnection("CONNECTION STRING")) {
5 using (SqlCommand comandoSql = conexao.CreateCommand()) {
6 comandoSql.CommandText = comando;
7 comandoSql.CommandType = CommandType.Text;
8 comandoSql.ExecuteNonQuery();
9 }
10 }
11 }
12 catch (SqlException sqlEx) {
13 new LogErros().RegistrarArquivoTexto(sqlEx.Message);
14 throw sqlEx;
15 }
16 }
17 }
Qual o problema desta classe? Simples, ela depende de uma classe concreta de log, como pode ser visto na linha 13. O que podemos fazer para resolver este problema? Em primeiro lugar precisamos extrair uma interface para a geração de logs, teríamos uma interface mais ou menos assim:
1 public interface ILogErros {
2 void RegistrarErro(string mensagemDeErro);
3 }
Agora fazemos nossa classe de banco de dados conhecer esta interface e criar uma forma de ter um objeto que implemente esta interface injetado:
1 public class SqlClass{
2 public void ExecutarComando(string comando) {
3 ILogErros logErros;
4 public SqlClass(ILogErros log){ this.logErros = log;}
5
6 try {
7 using (SqlConnection conexao = new SqlConnection("CONNECTION STRING")) {
8 using (SqlCommand comandoSql = conexao.CreateCommand()) {
9 comandoSql.CommandText = comando;
10 comandoSql.CommandType = CommandType.Text;
11 comandoSql.ExecuteNonQuery();
12 }
13 }
14 }
15 catch (SqlException sqlEx) {
16 this.logErros.RegistrarErro(sqlEx.Message);
17 throw sqlEx;
18 }
19 }
20 }
Na linha 3 criamos um campo na classe do tipo da interface. É importante perceber que agora nossa classe de banco de dados não conhece o objeto de log, ela apenas conhece sua interface. Ela não sabe como o log será gravado. Na linha 4 criamos um construtor que recebe um objeto que implementa a interface ILogErros, e este construtor irá garantir que quem quer que instancie a classe tenha que injetar um objeto de log para ela. E isto é Injeção de Dependências!
Este tipo de injeção de dependência é conhecido como Constructor Injection, ou seja, injeção via construtor. Agora para que consigamos instanciar nossa classe SqlClass precisamos passar um objeto que implemente ILogErros_, algo mais ou menos assim:
SqlClass sql = new SqlClass(new LogEmArquivoTexto());
Onde LogEmArquivoTexto implementa ILogErros.
Podemos usar o recurso de Inversão de Controle visto aqui para criarmos uma factory que já nos retorne um objeto SqlClass com a dependência injetada, nos poupando algum trabalho.
Em um próximo post veremos como utilizar o Unity, um contêiner de injeção de dependências da Microsoft. Abraços galera, espero que tenham gostado. Qualquer dúvida é só escrever.
Att,
Vinicius Quaiato.