Ok, então você começou a usar o Dependency Injection e viu que dava muito trabalho. A boa notícia é que existem vários frameworks por aí que ajudam a diminuir o trabalho e ainda a ter um código muito mais limpo.
Particularmente, eu gosto muito do StructureMap, principalmente porque ele nos permite utilizar o “Convention over Configuration”. Vamos ver jajá como isso funciona.
Bom, dando sequência no post anterior, vamos modificar aquele código para utilizar o StructureMap. A primeira coisa a fazer obviamente é baixar o framework e adicionar uma referência para o assembly StructureMap.dll.
O próximo passo é configurar o StructureMap, para isso vamos criar uma classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class StructureMapConfiguration { public static void Configure() { ObjectFactory.Initialize(InitializeStructureMap); } private static void InitializeStructureMap(IInitializationExpression x) { x.Scan(y => { y.Assembly("MvcApplication1"); y.With<defaultconventionscanner>(); }); } } |
O que fazemos nesse código e dizer para o ScrutureMap buscar no Assembly MvcApplication1 usando a convenção padrão. E o que é a convenção padrão? Geralmente quando criamos uma interface, como no nosso caso criamos a interface IClienteService criamos uma classe com a implementação padrão da interface chamada ClienteService. Essa é a convenção padrão, dessa forma, toda vez que precisarmos de um objeto que implemente a interface IClienteService o StructureMap buscará nos assemblies informados para ele, a classe de mesmo nome só que sem o I. Prático não? Nada de configurar XMLs e afins (embora o StructureMap permita isso).
Outra coisa que precisamos fazer é criar uma classe que será responsável pela criação dos nosso controllers. Isso é necessário porque por padrão o Asp.Net MVC cria os controllers apenas com o construtor padrão, sem parâmetros. Nossa classe fica assim:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class StructureMapControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(Type controllerType) { if (controllerType == null) return null; try { return ObjectFactory.GetInstance(controllerType) as Controller; } catch (StructureMapException) { System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave()); throw; } } } |
Pronto, agora vamos alterar a inicialização da aplicação no Global.asax, que deve ficar assim:
1 2 3 4 5 6 7 | protected void Application_Start() { RegisterRoutes(RouteTable.Routes); StructureMapConfiguration.Configure(); ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); } |
Uma última coisa, no nosso controller ClienteController tínhamos dois construtores, agora vamos deixar apenas um com o parâmetro necessário para funcionar:
1 2 3 4 5 | public IClienteService _service; public ClienteController(IClienteService service) { _service = service; } |
Pronto, isso é tudo o que é necessário. Mas se você quiser utilizar um XML para configurar suas classes, é possível. Dentro da classe de configuração, logo abaixo do método Scan, adicione:
1 | x.AddConfigurationFromXmlFile("structuremap.config.xml"); |
Isso fará que com que o StructureMap procure na raiz do site por um arquivo chamado structuremap.config.xml. Segue um exemplo de como deve ser esse arquivo:
1 2 3 4 5 6 7 | <structuremap mementostyle="Attribute"> <defaultinstance> PluginType="MinhaLibrary.Business.IClasseNegocio, MinhaLibrary.Business" PluggedType="MinhaLibrary.Business.ImplementacaoClasseNegocio, MinhaLibrary.Business" Scope="Singleton" /> </defaultinstance> </structuremap> |
É isso! E viva o Convention over Configuration!!!!