4. Inversión de control
Problemas en el uso de programación tradicional en capas
Para reemplazar o actualizar las dependencias es necesario cambiar las
clases.
Las implementaciones específicas de las dependencias tienen que estar
disponibles en tiempo de compilación.
Las clases son dificilmente testeables en un espacio aislado porque tienen
referencias directas. Esto significa que esas dependencias no pueden ser
reemplazadas por “Mocks”.
Las clases contienen código repetitive para tareas de CRUD y administración
de sus dependencias.
5. Inversión de control
Definición
Es un patrón de programación, basado en el principio de Hollywood, en el que el
flujo de ejecución de un programa se invierte respecto a los métodos de
programación tradicionales, en los que la interacción se expresa de forma
imperativa haciendo llamadas a procedimientos (procedure calls) o funciones.
Su diseño está pensado para permitir un menor acoplamiento entre componentes
de una aplicación y fomentar así la reutilización de los mismos y el testeo en
espacios aislados, haciendo uso para ello de Interfaces.
7. Inversión de control
Beneficios de su uso
Desacoplamiento de las clases de sus dependencias, con lo que de esta forma,
éstas podrán ser actualizadas o reemplazadas minimizando los cambios del
código.
Poder escribir clases que dependan de otras cuya implementación esppecífica
se desconoce en tiempo de compilación
Testear las clases en un espacio aislado sin hacer uso de sus dependencias.
Liberación de las clases de la tarea de ser responsables de la localización y la
administración del ciclo de vida de las dependencias.
10. Inyección de dependencias
Definición
Es un patrón de diseño orientado a objetos, en el que se suministran objetos
(Inyección) a una clase en lugar de ser la propia clase quien cree el objeto. El
término fue acuñado por primera vez por Martin Fowler.
11. Inyección de dependencias
No se instancian las dependencias de forma explícita. En vez de eso, se
realiza una declaración de las dependencias en la definición de la clase que,
por medio de un objeto constructor “Builder” se resuelven inyectando la
instancia específica en el momento de la instanciación de la clase que
contiene la dependencia.
14. Autofac
Definición
Es un contenedor de IoC para .NET que se encarga de administrar las dependencias
entre clases de forma que la aplicación sea fácilmente actualizable y por tanto,
escalable en tamaño y complejidad.
Enlaces a documentación
http://autofac.org/
https://code.google.com/p/autofac/
NUGET
http://nuget.org/packages/Autofac/
15. Autofac
Uso del contenedor
Registro de Componentes de forma individual
Registro de todos los Componentes de un ensamblado
Crear el contenedor
Obtener una instancia del contenedor
Registro de Interfaces con su implementación
var builder = new ContainerBuilder();
builder.Register(c => new TaskController(c.Resolve<ITaskRepository>()));
builder.RegisterType<TaskController>();
builder.RegisterInstance(new TaskController());
builder.RegisterAssemblyTypes(controllerAssembly);
var container = builder.Build();
var taskController = container.Resolve<TaskController>();
builder.RegisterType<TaskController>().As<IController>();
// enabling
var taskController = container.Resolve<IController>();
16. Autofac
Expresar las dependencias
Cuando hay más de una dependencia
Parámetro por defecto para las dependencias
Dependencias circulares
public class TaskController : IController
{
public TaskController(ITaskRepository tasks) { ... }
}
public TaskController(ITaskRepository tasks)
public TaskController(ITaskRepository tasks, ILog log)
public TaskController(ITaskRepository tasks, ILog log = null)
public TaskController(Lazy<ITaskRepository> tasks)
18. Autofac para MVC
El módulo de Autofac para MVC disponible también en NUGET nos permite realizar
operaciones habituales como el registro de los Controllers, los Model Binders, etc… de
forma automatizada
Registro de los Controladores
Registro de los Model Binders
Inyección de abstracciones HTTP
Inyección de Dependencias en Vistas
Inyección de Propiedades en FilterAttributes
NUGET
http://nuget.org/packages/Autofac.Mvc4/
19. Autofac para MVC
Registro de dependencias y del “resolvedor” de dependencias
Registro de los controladores manualmente
Registro de los controladores de un proyecto entero
Registro del “resolvedor” de dependencias
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// Other MVC setup...
var builder = new ContainerBuilder();
builder.RegisterType<HomeController>().InstancePerHttpRequest();
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
20. Autofac para MVC
Registro de Model Binders
Inyección de HTTP Abstractions
Registro de los controladores de un proyecto entero
var builder = new ContainerBuilder();
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
[ModelBinderType(typeof(string))]
public class StringBinder : IModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//do implementation here
}
}
builder.RegisterModule(new AutofacWebTypesModule());
21. Autofac para MVC
Inyectar dependencias en las vistas
builder.RegisterSource(new ViewRegistrationSource());
public abstract class CustomViewPage : WebViewPage
{
public IDependency Dependency { get; set; }
}
public abstract class CustomViewPage : ViewPage
{
public IDependency Dependency { get; set; }
}
@inherits Example.Views.Shared.CustomViewPage
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="Example.Views.Shared.CustomViewPage"%>
22. Autofac para MVC
Inyectar Properties en FilterAttributes
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(c => new Logger()).As<ILogger>().InstancePerHttpRequest();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
public class CustomActionFilter : ActionFilterAttribute
{
public ILogger Logger { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Logger.Log("OnActionExecuting");
}
}
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public ILogger Logger { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
Logger.Log("AuthorizeCore");
return true;
}
}
[CustomActionFilter]
[CustomAuthorizeAttribute]
public ActionResult Index()
{
// ...
}