ASP.NET MVC 3, IDependencyResolver com Microsoft Unity

by Felipe Oriani 21. julho 2011 11:29

Olá pessoal, dando continudade aos artigos sobre injeção de dependência (e inversão de controle), neste post pretendo mostrar de forma rápida como trabalhar com um container de dependências no ASP.NET MVC. Conforme os artigos anteriores, os exemplos utilizarão o Microsoft Unity.

Até a versão 2 no ASP.NET MVC, para resolver dependencias em nossos Controllers era necessário modificar a Controller Factory padrão (responsável por criar os controllers) do Asp.Net MVC herdando da classe DefaultControllerFactory e sobreescrevendo o método GetControllerInstance. Já na versão 3, este processo ficou mais fácil pois foi incorporada uma nova interface chamada IDependencyResolver que visa resolver dependencias de Controllers (onde podemos utilizar um container de dependencias para isto), veja sua declaração:

public interface IDependencyResolver {
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

Conhecendo esta interface, podemos realizar uma implementação básica junto a um container do Unity:

public class UnityDependencyResolver : IDependencyResolver
{
	private IUnityContainer container;

	public UnityDependencyResolver(IUnityContainer container)
	{
		this.container = container;
	}

	public object GetService(Type serviceType)
	{
		if (!container.IsRegistered(serviceType)) {
			if (serviceType.IsAbstract || serviceType.IsInterface) {
				return null;
			}
		}
		return container.Resolve(serviceType);
	}

	public IEnumerable<object> GetServices(Type serviceType)
	{
		return container.ResolveAll(serviceType);
	}
}

Uma vez tendo uma implementação desta interface e um container com todas as dependencias registradas, podemos seta-la como a “resolvedora” de dependencias em nosso projeto no arquivo global.asax no evento Application_Start, veja abaixo:

//declaração de nosso container de dependencias
private static UnityContainer _container;

protected void Application_Start()
{
	AreaRegistration.RegisterAllAreas();
	
    // criando nosso container de dependencias e registrando uma dependencia de exemplo.
	_container = new UnityContainer();
	_container.RegisterType(typeof (IPersonRepository), typeof (PersonRepository));
	
	RegisterGlobalFilters(GlobalFilters.Filters);
	RegisterRoutes(RouteTable.Routes);
	
    //modificando o DependencyResolver para a nossa customização passando o container.
	DependencyResolver.SetResolver(new UnityDependencyResolver(this._container));
}

protected void Application_End() 
{
    // ao finalizar a aplicação, libera o container
    if (_container != null)
	    _container.Dispose();
}

No exemplo acima, criamos um container do unity e registramos um dependencia de um repositorio simples como exemplo. Na última linha, do método Application_Start, informamos ao DependencyResolver através do método SerResolver que nossa classe UnityDependencyResolver (implementação de IDependencyResolver) será nossa “resolvedora” de dependencias. Com isso, quando um controller necessitar de um dependencia (seja via construtor ou propriedade) ela será resolvida pela DependencyResolver.

Veja abaixo uma imagem do momento que um controller é instanciado e sua dependencia sendo resolvida com um repositório simples.

 IDependencyResolver com Microsoft Unity

Repare que o controller depende do tipo de uma interface que está registrada no container do unity e o tipo concreto que é instanciado é o respectivo ao registro no container.

Caso você queira dar uma olhada nos fontes do ASP.NET MVC 3, e ver como a controller factory utiliza uma instância de IDependencyResolver para trabalhar, clique aqui e entenda melhor como este processo funciona.

Espero que gostem e ajudem em seus projetos.

Abraços.

Tags: , ,

ASP.Net MVC | Padrões de Projetos

Injeção de Dependência com Microsoft Unity (UnityContainer)

by Felipe Oriani 23. fevereiro 2011 05:45

 

Olá amigos! No post anterior, fiz uma breve introdução em um padrão chamado Injeção de Dependência, no qual gosto muito e utilizo em meus projetos. Neste post de hoje vou tentar demonstrar como utilizar um container para realizar a injeção de dependência de forma simples e prática. 

Existem várias bibliotecas que podem nos auxiliar com este processo, e particularmente tenho preferencial pela Microsoft Unity, pela facilidade que ela propõe. Existem outras como Ninject, Castle Windson, Spring.Net, entre outros.

Microsoft Unity

Inicialmente, o Unity fazia parte da Microsoft Enterprise Library, que até hoje é mantido pela Microsoft, que se trata de uma biblioteca de componentes (application block) que aplica as boas-práticas de desenvolvimento com .Net, práticas comuns do dia a dia como acesso a dados, validação, logging, entre outras. Com o Unity não foi diferente, passou a ser o bloco de injeção de dependência da Entreprise Library. Depois com o tempo, ele tornou-se independente e hoje estamos na versão 2.0. Você pode fazer o download do Microsoft Unity neste link.

http://www.microsoft.com/downloads/en/details.aspx?
FamilyId=2d24f179-e0a6-49d7-89c4-5b67d939f91b&displaylang=en

O Unity (assim como outras bibliotecas de injeção de dependência) fornece uma classe que tem como objetivo formar um Container de dependências, ou seja, em um container podemos registrar dependências que nosso software necessita e este por sua vez consegue construir objetos com estas dependências resolvidas.

Além da flexibilidade que ganhamos com a utilização de um container a produtividade aumenta, pois tudo no final parece ser um pouco mágico, bastando apenas solicitar um determinado tipo ao container que este nos retornara um objeto com suas dependências resolvidas e pronto para uso. Vamos a um exemplo prático.

Feito o download, instale o Unity em sua máquina de desenvolvimento e crie uma solução de testes no Visual Studio. Feito isso, adicione a referência do Unity (Microsoft.Pratices.Unity e Microsoft.Pratices.Unity.Interception.Configuration) como mostra na figura abaixo:

 

Figura 1: Adicionando referência para Microsoft Unity em projeto.
 

Feito isso, podemos começar a utilizar um container. Primeiramente vamos criar alguns exemplos para ilustrar o uso básico do container. A listagem abaixo, exibe um pequeno exemplo de uma interface para realizar log de aplicações e três simples implementações desta interface.

public interface ILogDeEvento
{
    void Escrever(string mensagem);
    void Escrever(string chave, string mensagem);
}

public class LogEvent : ILogDeEvento
{
    public LogEvent() { }

    private const string ChavePadrao = "MSUnitTest";
    public void Escrever(string mensagem)
    {
        Escrever(ChavePadrao, mensagem);
    }

    public void Escrever(string chave, string mensagem)
    {
        // cria-se a chave caso esta ainda não exista.
        if (!EventLog.SourceExists(chave))
        {
            EventLog.CreateEventSource(chave, "MSUnitTest");
        }

        //escreve no eventLog
        var myLog = new EventLog { Source = chave };
        myLog.WriteEntry(mensagem);
    }
}

public class LogXml : ILogDeEvento
{
    private const string Caminho = "LogXml.xml";

    public void Escrever(string mensagem)
    {
        using (var stream = new StreamWriter(Caminho))
        {
            var xml = new XmlSerializer(typeof(string));
            xml.Serialize(stream, mensagem);
        }
    }

    public void Escrever(string chave, string mensagem)
    {
        Escrever(mensagem);
    }
}


public class LogTxt : ILogDeEvento
{
    public LogTxt()
    {
    }

    private const string Caminho = "logDeEventos.log";
    public void Escrever(string mensagem)
    {
        using (var stream = new StreamWriter(Caminho, true))
        {
            stream.WriteLine(mensagem);
            stream.Flush();
        }
    }

    public void Escrever(string chave, string mensagem)
    {
        using (var stream = new StreamWriter(Caminho, true))
        {
            stream.WriteLine(string.Format("{0}: {1}", chave, mensagem));
            stream.Flush();
        }
    }
}

 

Listagem 1: Exemplo para implementação


Até aqui, nada de novo. Voltando ao projeto de testes, vamos adicionar um teste de unidade, a listagem abaixo demonstra como podemos utilizar o container da Microsoft Unity:

[TestClass]
public class UnityTest
{
    // declaramos um container...
    private IUnityContainer _container;

    public UnityTest()
    {
    }

    [TestInitialize()]
    public void UnityInit()
    {
        // realizamos a instância deste container...
        _container = new UnityContainer();

        // registramos uma dependência no container...
        _container.RegisterType(typeof (ILogDeEvento), typeof (LogTxt));
    }
        
    [TestCleanup()]
    public void UnityDispose()
    {
        // liberamos o container do heap..
        _container.Dispose();
    }
        
    [TestMethod]
    public void Deve_Resolver_Dependencia()
    {
        // obtendo um logger de eventos pelo container...
        var logger = _container.Resolve<ILogDeEvento>();

        // invocando um método da instância resolvida pelo container...
        logger.Escrever("Mensagem de erro para ser gerada em TXT.");
    }
}

Listagem 2: Implementação do Teste utilizando Unity Container.


Como podemos observar no código acima, no escopo da classe temos uma declaração de um objeto da interface IUnityContainer, que é a interface implementada pelo nosso container. No método UnitInit (que possui o atributo [TestInitialize]) realizamos a instância deste objeto e registramos uma possível dependência passando dois tipos, onde o primeiro tipo é o requisitado e o segundo o que será utilizado para resolver. Observe que o tipo requisitado foi colocado a Interface ILogDeEventos (o que é uma boa prática da orientação a objetos, uma vez que podemos utilizar instâncias que implementam tal interface em sua concretização) e o tipo que a resolve é uma implementação dela LogTXT. Escrevemos um método de testes simples, Deve_Resolver_Depencias e neste implementamos a resolução deste tipo registrado pelo  container, e se executarmos este teste, vemos nos resultados a saída do log em TXT. O mesmo vale se trocarmos o tipo de resolução para Xml ou EventLog.

Boas práticas com Injeção de Dependências.

Hoje em dia fala-se muito em realizar DI pelos construtores, propriedades ou métodos. Vou demonstrar aqui como realizar injeção de dependência pelo construtor, que na minha opinião é o tipo de dependência para um objeto que mais faz sentido, uma vez no construtor, sem tal dependência torna-se impossível construir o objeto.

Para ilustrar um exemplo disso, vamos criar uma classe que possui a implementação de um Logger, para um exemplo real, um Mock. A listagem abaixo exibe um pequeno exemplo abaixo:

public class Mock<T>
{
    private readonly ILogDeEvento _eventLog;
    public Mock(ILogDeEvento eventLog)
    {
        _eventLog = eventLog;
    }

    public void Salvar(T entidade)
    {
        // persistir objeto
        _eventLog.Escrever(string.Format("Objeto {0} salvo com sucesso. \n Valor: {1}", entidade.GetType().Name, entidade.ToString()));
    }
}

Listagem 3: Implementação de exemplo de Mock com dependência em construtor. 
 

Observe que além de um classe genérica, no construtor deste recebemos um objeto da interface ILogDeEventos e setamos em uma variável interna no escopo da classe. Pois bem, voltando a classe de testes, vamos criar um novo método para realizar um simples deste exemplo. Veja o código comentado abaixo:

[TestClass]
public class UnityTest
{
    // declaramos um container...
    private IUnityContainer _container;

    public UnityTest()
    {
    }

    [TestInitialize()]
    public void UnityInit()
    {
        // realizamos a instância deste container...
        _container = new UnityContainer();

        // registramos uma dependência no container...
        _container.RegisterType(typeof (ILogDeEvento), typeof (LogTxt));

        // registramos a dependência para o Mock genérico
        _container.RegisterType(typeof(Mock<>), typeof(Mock<>));

    }
        
    [TestCleanup()]
    public void UnityDispose()
    {
        // liberamos o container do heap..
        _container.Dispose();
    }
        
    [TestMethod]
    public void Deve_Resolver_Dependencia()
    {
        // obtendo um logger de eventos pelo container...
        var logger = _container.Resolve<ILogDeEvento>();

        // invocando um método da instância resolvida pelo container...
        logger.Escrever("Mensagem de erro para ser gerada em TXT.");
    }


    [TestMethod]
    public void Deve_Resolver_Dependencia_Em_Objeto()
    {
        // obtendo um Mock pelo container...
        var mock = _container.Resolve<Mock<string>>();

        // invocando um método da instância resolvida pelo container...
        mock.Salvar("Felipe Oriani");
    }
}

Listagem 4: Implementação do teste do uso do Mock junto ao Container de dependência.

A instância de um Mock tem o objeto de simular o comportamento de um objeto real de nossa aplicação e neste caso, estou utilizando este como um Repositório, que recebe em seu construtor um ILodDeEvento. Em nosso exemplo, estou registrando o Mock no container, pois este tem dependência (que devem ser resolvidas) e no método Deve_Resolver_Dependencia_Em_Objeto(), fiz um pequeno exemplo da crianção de um Repositório de Strings. Ao executar este teste, podemos olhar no output dos testes, que os logs são executados sem problemas, veja a imagem abaixo:

 

 

Figura 2: Resultado da saída do Log (em TXT).

 

Portando isso para uma aplicação do mundo real, se um dia resolvermos mudar nossa forma de realizar log da aplicação para XML ou EventLog, podemos simplesmente alterar a resolução para o container que funcionará sem problemas, uma vez que todas estas implementações de Log implementam a mesma interface, torna-se simples.

Bem pessoal o que gostaria de demonstrar neste post era isso.

Em um próximo post, pretendo abordar como utilizar o Unity no Asp.Net MVC para resolver dependências em Controllers e Repositórios de dados. Os exemplos utilizados neste post, estão no rodapé.

Vou deixar alguns links no final que utilizei como estudo e referência.

Espero que tenha gostado.

Abraços

Exemplo demonstrativo
MsUnityTests-Exemplo.zip (508,09 kb)

Links e Referências

http://en.wikipedia.org/wiki/Dependency_injection

http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx

http://viniciusquaiato.com/blog/injecao-de-dependencia-com-ms-unity/

http://goo.gl/OKJIx

Tags: ,

C# | Padrões de Projetos

Injeção de Dependência (Dependency Injection)

by Felipe Oriani 8. fevereiro 2011 06:01

 

Desde que comecei meus estudos com arquitetura de software passei a prezar mais pela qualidade do código e a facilidade de trabalhar com boas práticas.  Existe um padrão chamado Injeção de Dependência no qual será assunto deste breve post. O que é e para que serve? Como utilizá-lo? São questões que tentarei abordar durante o post.

O que é Injeção de Dependência e para que serve?

Segundo a Wikipédia, Injeção de Dependência é um padrão de desenvolvimento de software utilizado quando necessitamos manter um baixo acoplamento entre as camadas (módulos) de um sistema. Mas o que seria este acoplamento? O acoplamento dá-se a partir do momento em que você gera uma nova instância direta de uma classe que pertence a outro módulo em um segundo módulo, ou seja, este passa a depender diretamente daquele tipo e não de uma abstração. Um exemplo simplista disso:

 

public class CompraService {
   public void PagarCompra(Compra compra) {
       var repositorio = new RepositorioDeCompra();
       repositorio.PagarCompra(compra);
   }
}

 

Neste exemplo, a partir do momento que definimos uma instância do RepositorioDeCompra()  (linha 3) em nosso serviço, estamos acoplando diretamente nosso repositório ao serviço. Ou seja, ele depende diretamente da referência da classe RepositorioDeCompra. Isso funciona perfeitamente, mas poderíamos melhorar um pouco a fim de desacoplar nosso serviço.

Mas como podemos melhorar isso?

É possível realizar uma abstração utilizando uma interface, ou seja, depender de uma implementação de uma interface ao invés de uma classe concreta. Com isso temos a vantagem de mudar a instância no momento em que necessitarmos um exemplo:

 

public class CompraService {

   protected IRepositorioDeCompra Repositorio {
       get;
       private set;
   }

   public CompraService(IRepositorioDeCompra repositorio) {
      this.Repositorio = repositorio;
   }
   public void PagarCompra(Compra compra) {
      this.Repositorio.PagarCompra(compra);
   }
}


Podemos ver que no exemplo, utilizamos uma abstração do RepositorioDeCompra, ou seja, uma interface que contém assinaturas de métodos que devem ser implementados pela instância a ser passada no construtor do serviço (que deixa explícito o requisito; podemos trabalhar com dependência em propriedades ou parâmetro em métodos; em tempo vamos  entender o conceito em construtores). Isso nos da uma flexibilidade maior, pois podemos passar qualquer objeto de uma classe que implemente esta interface, mantendo o baixo acoplamento entre a camada de serviço e sua intermediaria. E para finalizar um exemplo desta interface e suas implementações:

 

interface IRepositorioDeCompra {
    void Salvar(Compra compra);
    void Excluir(Compra compra);
    IEnumerable<Compra> ObterTodos();
    Compra Obter(int id);
    void PagarCompra(Compra compra);
    void ReceberCompra(Compra compra);
    void CancelarCompra(Compra compra);   
}

public class RepositorioDeCompra : IRepositorioDeCompra { ... }
public class RepositorioDeCompraNHibernate : IRepositorioDeCompra { ... }
public class RepositorioDeCompraEF : IRepositorioDeCompra { ... }
public class RepositorioDeCompraAdo : IRepositorioDeCompra { ... }
public class RepositorioDeCompraXml : IRepositorioDeCompra { ... }

 


Com isso, podemos passar qualquer uma dessas instâncias, pois estas implementam IRepositorioDeCompra.  Na prática isso poderia ser utilizado da seguinte forma:

 

var servico = new CompraService(new RepositorioDeCompraNHibernate());
var servico = new CompraService(new RepositorioDeCompraEF());
var servico = new CompraService(new RepositorioDeCompraAdo());

 

Apesar de ser simples o assunto, recomendo que utilizem um container de dependências, que será assunto para um próximo post.

Espero que tenham gostado e entendido.

Um abraço!

 

Referências:
http://en.wikipedia.org/wiki/Dependency_injection
http://viniciusquaiato.com/blog/injecao-de-dependencia/

Tags: ,

C# | Padrões de Projetos

ASP.Net MVC - Desenvolvendo para o "Core" da Web

by Felipe Oriani 21. maio 2010 12:23

Olá a todos! Algum tempo atrás a Microsoft já havia anunciado a versão MVC de sua plataforma de desenvolvimento web, o ASP.Net MVC. Esta por sua vez não veio como um sucessor da atual versão do ASP.Net WebForms e sim como uma alternativa tendo suas diferenças. Ambas as tecnologias são produtivas e eficientes e dizer que uma é melhor ou deixa de ser que a outra é pura falta de conhecimento.

Atualmente estamos na versão 2.0 do ASP.Net MVC, e espero que a Microsoft continue promovendo ambas as versões do ASP.Net, MVC e Webforms. Você pode fazer o download da versão 2.0 aqui e instalar, lembrando que o ASP.Net MVC contém compatibilidade apenas com as versões 2008 ou superior do Visual Studio.

Uma das principais vantagens que vejo no MVC perante ao Webforms, é que o primeiro foi desenvolvido diretamente para trabalhar já aplicando padrões de projetos (design patterns) e desenvolvimento orientado a testes (TDD) enquanto no segundo está mais focado no desenvolvimento orientado a componentes (entenda, como server controls) e eventos. Devemos ter em mente que tanto o ASP.Net MVC como o Webforms, contém o mesmo Núcleo, que é o ASP.Net CORE, o que permite o uso de diversos recursos que aplicamos em webforms, como chaching, logging, etc.

No ASP.Net MVC todo o output da aplicação web e todo o controle de estado ficam por conta do desenvolvedor (ou time de desenvolvimento) que por sua vez recomenda-se estar maduro em relação as Web Standards assim como em ASP (3.0), PHP e outras tecnologias. Dizer que isso é uma falta de produtividade é no mínimo imaturidade em relação a inovação tecnológica, pois em minha visão temos uma leve vantagem em relação ao ASP.Net Webforms, por exemplo: componentes de interfaces como grids, inputs, seletores, menus, etc...  podemos encontrar aos montes como extenções da JQuery, ExtJS, e outras bibliotecas client-side (javascript ou css) tornado as mais fáceis de se implementar em uma aplicação ASP.Net MVC pelo fato de termos controle do output, sem precisar se preocupar com os imensos campos conhecidos como ViewState que persistem o estado de cada server control (pecando um pouco na performace e output) em um webform.

Para quem estava acostumado a ASP.Net Webforms em montar suas URLs diretamente no sistema de arquivos, o cenário muda um pouco no ASP.Net MVC que por sua vez, utiliza um esquema de tabela de rotas que monta as URLs diretamente ligada aos Controllers que por sua vez retornam para o browser renderizar uma View, podendo passar um Model, mantendo URLs mais amigáveis aos usuários além de ter maior facilidade para integrar com otimizadores de buscas e SEO.

A versão 2.0 ainda trás novos recursos como maior suporte a Areas (que na versão 1.0 era possível porém exigia certo esforço do desenvolvedor para integrar), validação do Model em Client e Server side acesso assíncrono aos controllers, integração com sub-sessões (através do método Html.RenderAction que permite que a view renderize outra Action [outra View]) como resultado HTML, entre outros.

 

Existe um projeto demonstrativo no codeplex chamado MVC Music Store que aplica padrões de projetos junto a uma aplicação ASP.Net MVC 2.0. Trata-se de uma pequena loja virtual com um carrinho de compras implementado em C# e Entity Framework 4.0. Acesse o link do projeto em http://mvcmusicstore.codeplex.com/, faça o download e bons estudos.

 

 

 

Espero que gostem e bons estudos.

Abraços

Tags: , , ,

.Net Framework | ASP.Net MVC | Padrões de Projetos

Sobre

Sou Felipe Oriani e trabalho com desenvolvimento web desde 2004, com tecnologias Microsoft como Asp e Asp.Net utilizando as linguagens C# e Vb.Net. Bacharel em Ciência da Computação pela Escola de Engenharia de Piracicaba,  MCTS (.Net Framework 3.5, ASP.NET Applications). Conheça um pouco mais sobre meu CurrículumVeja mais 

Social

profile for Felipe at Stack Overflow, Q&A for professional and enthusiast programmers

Selos

MCTS .Net Framework 3.5, ASP.NET Developer

MCP - Microsoft Certified Professional