Injeção de dependência com Autofac

Fala galera!

Sabe aquele projeto antigo, gigante, que não dá pra refazer? Será que dá pra colocar Injeção de dependência nele?

Vamos pegar um cenário que deve ser muito comum e tentar fazer injeção de dependência nele:
Um projeto com 3 camadas, Model, Data Access e Business Logic:

1) Vamos criar um projeto, pode ser em ASP .NET MVC, sem autenticação, sem nada.
2) Vamos adicionar um projeto Windows Class Library chamado Core, onde vamos colocar o “Acesso a dados”.
3) Vamos adicionar adicionar o AutoFac na camada MVC. Pelo Package Manager Console:

Install-Package Autofac.Mvc5

4) Agora vamos criar nosso Core. Separei o Core em duas pastas: Data e Services. Dentro da pasta Data ficará os Models, BusinessLogic e o DataAccess.

Neste projeto não criei o DataAccess para ficar mais simples o exemplo.

CoreFiles

Os services foram criados para não acessar diretamente o BusinessLogic pela camada Web, poderia até ser colocado em um projeto separado.

Core/Data/Models/BaseEntity.cs

namespace Core.Data.Models
{
    public abstract class BaseEntity
    {
        public int Id { get; set; }
    }
}

Core/Data/Models/Example.cs

namespace Core.Data.Models
{
    public class Example : BaseEntity
    {
        public string Title { get; set; }
    }
}

Core/Data/ExampleBL.cs

using Core.Data.Models;
using System.Collections.Generic;

namespace Core.Data
{
    public class ExampleBL : IBusinessLogic<Example>
    {
        public IEnumerable<Example> GetAll()
        {
            return new List<Example>()
            {
                new Example() { Id = 1, Title = "Test 1" },
                new Example() { Id = 2, Title = "Test 2" },
            };
        }

        public Example GetById(int id)
        {
            return new Example() { Id = id, Title = "No Title" };
        }
    }
}

Core/Data/IBusinessLogic.cs

using Core.Data.Models;
using System.Collections.Generic;

namespace Core.Data
{
    public interface IBusinessLogic<Entity> where Entity : BaseEntity
    {
        Entity GetById(int id);

        IEnumerable<Entity> GetAll();
    }
}

Core/Data/Services/IExampleService.cs

using Core.Data.Models;
using System.Collections.Generic;

namespace Core.Services
{
    public partial interface IExampleService
    {
        IEnumerable<Example> GetAll();
    }
}

Core/Data/Services/ExampleService.cs

using System.Collections.Generic;
using Core.Data.Models;
using Core.Data;

namespace Core.Services
{
    public class ExampleService : IExampleService
    {
        private readonly IBusinessLogic<Example> _exampleBL;

        public ExampleService(IBusinessLogic<Example> exampleBL)
        {
            this._exampleBL = exampleBL;
        }

        public IEnumerable<Example> GetAll()
        {
            return this._exampleBL.GetAll();
        }
    }
}

5) Agora vamos configurar a aplicação Web.
Adicione o projeto Core como referência para podermos usá-lo.

Depois abra o arquivo Global.asax.cs e adicione no final do método Application_Start():

            #region Dependency Injection

            var builder = new ContainerBuilder();

            // Register mvc controllers
            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            // Register BusinessLogic
            builder.RegisterType<ExampleBL>().As<IBusinessLogic<Example>>().InstancePerRequest();

            // Register Services
            builder.RegisterType<ExampleService>().As<IExampleService>().InstancePerRequest();

            var container = builder.Build();

            // Set MVC DI resolver to use our Autofac container
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            #endregion

6) Para testar o funcionamento, vamos modificar o HomeController.

using Core.Services;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        private readonly IExampleService _exampleService;

        public HomeController(IExampleService exampleService)
        {
            this._exampleService = exampleService;
        }

        public ActionResult Index()
        {
            ViewData["ExampleList"] = this._exampleService.GetAll();
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

Vai ser injetado no construtor do Controller o nosso service.

Vamos alterar também a View para mostrar o resultado:

@{
    ViewBag.Title = "Home Page";
    var list = ViewData["ExampleList"] as List<Core.Data.Models.Example>;
}

<h1>Show data</h1>
<table>
    <thead>
        <tr>
            <th>Id</th>
            <th>Title</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in list)
        {
            <tr>
                <td>@item.Id.ToString()</td>
                <td>@item.Title</td>
            </tr>
        }
    </tbody>
</table>

Resultado:
Screenshot_3

Código fonte:
https://github.com/leonardohof/AutoFacDaoExample

Até a próxima!


Curta também minha página no Facebook para ficar por dentro das novidades:
https://www.facebook.com/devleonardohofling