[Patrones] Intercepción de llamadas a métodos (III) IoC containers

Continuando y para cerrar ya la serie de posts sobre la intercepción de llamadas a métodos (Aquí está el primero y segundo) vamos a terminar con un ejemplo usando un contenedor de dependencias.

Para este ejemplo vamos a usar Castle Windsor. Si intentamos instalarlo usando la consola de NuGet recibiremos este error:

image

La solución a este error la he encontrado en stackoverflow y es usando el pipeline de powershell para instalar todos los paquetes que Castle.Windsor necesita:

image

Una vez instalado, vamos a crear el interceptor y para ello vamos a implementar la interfaz IInterceptor:

{

    private readonly ISecurityValidation _securityValidation;

 

    public SecurityInterceptor(ISecurityValidation securityValidation)

    {

        if (securityValidation == null) 

            throw new ArgumentNullException("securityValidation");

 

        _securityValidation = securityValidation;

    }

 

    public void Intercept(IInvocation invocation)

    {

        if (_securityValidation.Validate())

            invocation.Proceed();

        else

        {

            throw new SecurityException("No tienes permisos!");

        }

    }

}

Creamos un constructor parametrizado al que le vamos a inyectar nuestra implementación para la controlar la seguridad de nuestra aplicación e implementamos el método Intercept, que será donde ejecutemos la llamada a nuestro servicio o proveedor de validación que vamos a implementar.

La interfaz ISecureValidacion y su implementación son muy sencillas para no complicar el ejemplo:

 

public interface ISecurityValidation

{

    bool Validate();

}

 

// Para no complicar la demo he optado por implementar un proveedor de validación

// sencillo, aquí podrías implementar tu validación personalizada

public class SecurityValidation : ISecurityValidation

{

    public bool Validate()

    {

        return true;

    }

}

 

Ahí podriamos añadir una lógica de validación controlando el método al que se está llamandoy quién lo está llamando, que se lo podemos pasar desde el parametro IInvocation que recibe el método Intercept del interceptor. Esto ya a gusto del programador y además todo esto nos sirve para implementar auditoría, trazas, logging… no solo seguridad.

 

Por último la aplicación de consola:

static void Main(string[] args)

{

   IWindsorContainer windsorContainer = new WindsorContainer();

   windsorContainer.Register(

       Component.For<SecurityInterceptor>());

   windsorContainer.Register(

       Component.For<IOrderRepository>().ImplementedBy<SqlOrderRepository>());

   windsorContainer.Register(

       Component.For<IOrderService>().ImplementedBy<OrderService>().

           Interceptors<SecurityInterceptor>());

   windsorContainer.Register(

       Component.For<ISecurityValidation>().ImplementedBy<SecurityValidation>());

 

   var orderService = windsorContainer.Kernel.Resolve<IOrderService>();

 

   var order = new Order

   {

       Id = Guid.NewGuid(),

       Total = 102.4M

   };

 

   try

   {

       orderService.Submit(order);

   }

   catch (SecurityException securityException)

   {

       Console.WriteLine(securityException.Message);

   }

 

   Console.Read();

}

Como podéis observar, registramos las dependencias, el interceptor y el punto interesante es cuando añadimos el interceptor al servicio:

windsorContainer.Register(

                Component.For<IOrderService>().ImplementedBy<OrderService>().

                    Interceptors<SecurityInterceptor>());

Además Castle Windsor nos inyectará la implementación del proveedor/servicio de validación en nuestro interceptor.

Nota: Los contenedores ahora permiten registrar las dependencias utilizando expresiones lambdas con lo que podemos casi automatizar el proceso de registro de dependencias sin utilizar mucho código.

Si ejecutamos la aplicación podemos observar como se está interceptando la llamada:

image

y al final, como no tenemos permisos:

image

Pues con esto finalizamos la serie de intercepción de llamadas. En este caso lo hemos hecho con la seguridad pero como he mencionado ante se utilizar para otras cosas. A mí personalmente me gusta mucho esta manera de interceptar las llamadas me parece la más elegante aunque claro está necesitas de un contenedor de dependencias y pagar un pequeño precio por el rendimiento que en algunos casos será asumible y necesario y en otros no.

Un saludo y espero que os haya gustado.

Un comentario en “[Patrones] Intercepción de llamadas a métodos (III) IoC containers”

  1. Hola tocayo! 🙂
    Uhm… en el primer bloque de código me parece que te has ‘comido’ la primera línea de código, que debe ser algo parecido a esto:

    public class SecurityInterceptor:IInterceptor

    El resto, en la línea: Un pedazo de post. Muy bueno! 🙂
    Saludos,

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *