Implemente inversão de controle (IoC) com Castle Windsor

25/08/2010 at 11:51 Deixe um comentário

Para quem conhece os 5 princípios de programação orientada a objetos batizados com o acrônimo SOLID, sabe que o principio de inversão de Dependência prega que suas classes devem depender de abstrações ao invés de implementações concretas. Seguir esse princípio deixa a sua classe mais flexível e, por tabela, mais testável. Um dos meios de implementar esse principio é usar a técnica de inversão de controle (IoC), que delega a responsabilidade por instanciar as dependências concretas para a classe chamadora. Esta, por sua vez, injeta (injeção de dependência) estas instâncias na classe que vai utilizá-las. O problema dessa abordagem é que o seu código pode ficar mais complexo se a classe for utilizada em pontos diferentes do código. Deixando um rastro indesejado, com a instanciação das dependências localizadas em cada classe chamadora.

Um dos modos de resolver o problema é utilizar um framework que disponibilize um contêiner de injeção de dependência. Isso é feito eliminando a injeção de dependência via construtor ou get/set e fazendo a instanciação das dependências concretas de forma dinâmica dentro da própria classe.

Um dos frameworks mais utilizados  no mundo .NET é o Castle Windsor. E nas próximas linhas vou mostrar como implementar a inversão de controle no seu projeto utilizando a versão 2.5 desse framework, o Microsoft Visual Studio 2010 e C#.

Projeto exemplo:

1. Baixe a biblioteca no endereço abaixo e descompacte na sua máquina:

http://www.castleproject.org/castle/download.html

2. Crie um projeto do tipo Console Application e referencie os assemblies Castle.Core e Castle.Windsor:

3. Crie a interface IIdentidadeRepositorio e as classes Identidade, IdentidadeServico e IdentidadeRepositorio:

Classe Identidade:

    public class Identidade
    {
        private int id;
        private string nome;
        private string cpf;
        private string cnpj;

        public virtual int Id
        {
            get{return id;}
            set{id = value;}
        }

        public virtual string Nome
        {
            get{return nome;}
            set{nome = value;}
        }

        public virtual string Cpf
        {
            get{return cpf;}
            set{cpf = value;}
        }

        public virtual string Cnpj
        {
            get{return cnpj;}
            set{cnpj = value;}
        }
    }

Interface IIndentidadeRepositorio:

    public interface IIdentidadeRepositorio
    {
        void Salvar(Identidade identidade);
    }

Classe IndentidadeRepositorio:

    public class IdentidadeRepositorio: IIdentidadeRepositorio
    {
        #region IIdentidadeRepositorio Members
        public void Salvar(Identidade identidade)
        {
            Console.WriteLine("Entidade identidade salva com sucesso!");
            Console.ReadLine();
        }
        #endregion
    }

Classe IndentidadeServico:

    public class IdentidadeServico
    {
        private IIdentidadeRepositorio repositorio;

        public IdentidadeServico()
        {
            this.repositorio = new IdentidadeRepositorio();
        }

        public void Salvar(Identidade identidade)
        {
            if (identidade == null)
                throw new NullReferenceException("Informe o parâmetro identidade!");
            if (string.IsNullOrEmpty(identidade.Cpf) && string.IsNullOrEmpty(identidade.Cnpj))
                throw new NullReferenceException("Informe o CPF ou o CNPJ!");

            repositorio.Salvar(identidade);
        }
    }

Classe Program:

        static void Main(string[] args)
        {
            Identidade identidade;
            IdentidadeServico servico;

            Console.WriteLine("Pressione qualquer tecla para continuar...");
            Console.ReadLine();

            identidade = new Identidade{Cpf = "13191607862"};
            servico = new IdentidadeServico();
            servico.Salvar(identidade);
        }

4. Agora aplique o conceito de inversão de controle na classe IdentidadeServico:

Classe  IdentidadeServico:

        public IdentidadeServico(IIdentidadeRepositorio repositorio)
        {
            this.repositorio = repositorio;
        }

Classe Program:

        static void Main(string[] args)
        {
            ...
            servico = new IdentidadeServico(new IdentidadeRepositorio);
            ...
        }

5. A partir desse ponto, podemos simplificar o código utilizando o Castle Windsor para instanciar a dependência concreta na própria classe IdentidadeServico.

Adicione ao projeto um arquivo App.Config e inclua a seguinte configuração:

  
    name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,
          Castle.Windsor"/>

A tag compenent especifica qual dependência concreta o Castle vai utilizar para uma determinada interface, e é  composta pelos seguintes atributos:

id: Identifidor único do componenete;
service: Identifica a interface e o seu namespace;
type: Identifica a classe concreta e o seu namespace;

Agora que o Castle está configurado podemos utilizar o seu contêiner para instânciar dinamicamente a dependência concreta:

Classe IdentidadeServico:

        ...
        IWindsorContainer conteiner = new WindsorContainer(new XmlInterpreter());

        public IdentidadeServico()
        {
            this.repositorio = conteiner.Resolve();
        }
        ...

Você pode alterar a classe Program para retirar a referência da classe IdentidadeRepositorio:

            ...
            servico = new IdentidadeServico();
            ...

Conclusão:

Algumas vezes utilizar conceitos avançados de orientação a objeto pode inserir uma complexidade indesejada no seu código, no caso acima, foi mostrado como podemos implementar a inversão de dependência utilizando Castle.Windsor sem adicionar uma complexidade desnecessária no código.

[]’s
Eduardo Ernandes da Silva
Arquiteto de Sistemas

Anúncios

Entry filed under: Frameworks. Tags: , , , .

Objeto de Valor Como mapear corretamente um objeto de valor usando Fluent NHibernate

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

Trackback this post  |  Subscribe to the comments via RSS Feed


Arquivos

Feeds

Calendário

agosto 2010
D S T Q Q S S
« jun   set »
1234567
891011121314
15161718192021
22232425262728
293031  

%d blogueiros gostam disto: