DIP – Principio de Inversión de Dependencias

Un post que tenía pendiente hace mucho tiempo era acerca del quinto principio SOLID llamado Principio de Inversión de Dependencias (Dependency Inversion Principle). Este principio nos dice que “dependamos de abstracciones, no de concreciones”. Tío Bob plantea dos puntos en la definición de este principio:

A. Las clases de alto nivel no deberían depender de las clases de bajo nivel. Ambas deberían depender de las abstracciones. B. Las abstracciones no deberían depender de los detalles. Los detalles deberían depender de las abstracciones.

Este principio, en conjunto con el resto de los principio SOLID, están orientados a reducir problemas relacionados con el mal diseño (aún cuando tengamos el código bien organizado en clases). Tio Bob  dice que en todo mal diseñose presentan alguna de las siguientes características:

  • Rigidez: un cambio afecta a muchas partes de un sistema.
  • Fragilidad: cada cambio genere problemas en lugares inesperados.
  • Inmovilidad: imposible de reusar.

Una forma muy simple de detectar un mal diseño es cuando tenemos “miedo” de tocar el código, porque creemos que en alguna parte algo se va a romper. Veamos un ejemplo de código mal diseñado y como podemos mejorarlo aplicando los principios SOLID, sobre todo DIP. Continuando con el mismo tema de los últimos post de la serie, supongamos que tenemos la clase PrecesoAutorizacionTarea que contiene el método Iniciar(). Este método se encarga, entre otras cosas, de loggearinformación acerca del inicio del proceso y el plazo máximo de aprobación de la tarea:

Definición clase ProcesoAutorizacionTarea

Definición clase ProcesoAutorizacionTarea

Es fácil detectar varios “errores” de diseño en la implementación del método. El primero de ellos es que es un diseño rígido. Supongamos que tenemos que agregar una nueva propiedad a la clase TxtLog para especificar el path o file del archivo de log a utilizar? Esta claro que deberíamos cambiar todas las instancias de TxtLog en el código, salvo que quisiéramos registrar “todo” en el archivo de log especificado por default (pero en tal caso, no tendría sentido dicha propiedad).

Para resolverlo, supongamos que decido especificar esta propiedad “a mano” (logger.Path = “…”;) en todas las porciones de código que sean necesarias (es decir, donde no me sea útil el archivo por default). En tal caso nos encontrarímos con un diseño frágil, ya que si nos olvidamos de especificarlo, estaríamos registrando información en un archivo de log, que sería el incorrecto. Algo similar ocurre con el calculo del plazo máximo de autorización de la Tarea… qué pasa si necesito realizar el mismo cálculo en otro módulo? O qué pasa si ahora tengo un nuevo tipo de tarea? Es realmente responsabilidad de la clase ProcesoAutorizacionTarea realizar dicho cálculo?… esta claro que las respuestas a estas preguntan nos conducen ante un mal diseño. Bien, para poder solucionar estos problemas, vamos a realizar una serie de cambios, el primero respecto al lugar donde se instancia el objeto TxtLog:

Resolviendo problemas de rigidez y fragilidad

Resolviendo problemas de rigidez y fragilidad

Como podemos ver, ahora la instancia de TxtLog la recibe el constructor de la clase ProcesoAutorizacionTarea, por lo que cada cambio que tengamos que realizar sobre dicha instancia, podemos hacerlo en un único lugar. Notemos que en este caso estamos “inyectando” al objeto ProcesoAutorizacionTarea  un objeto TxtLog, es decir su dependencia. Esto se denomina Inyección de Dependencias y sobre este tema hemos hablado en varios post. Bien, resuelto esto, tenemos otro problema, seguimos teniendo un mal diseño, ya que es inmóvil. Supongamos que el día de mañana, se desea utilizar un DbLog o XmlLog. Este cambio podría ser un dolor de cabeza, ya que el proceso depende exclusivamente de TxtLog. Algo similar ocurre si necesitamos realizar el calculo de un proceso “SEMI-AUTOMATICO”? Entonces veamos como corregir este error de diseño. Antes que nada vamos a generar las interfaces ILog e ICalculadorPlazosTarea – esta última es una pobre traducción que se me ocurrió, reconozco que con el tiempo se me hizo complicado definir nombres en español 🙂 -.

Definiendo las interfaces

Definiendo las interfaces

Lo siguiente, generar las clases que lo implementen. Por un lado tendremos TxtLog que implementa ILog y por el otro dos nuevas clases llamadas CalculadorPlazosTareaX CalculadorPlazosTareaY que implementan ICalculadorPlazosTarea. Comencemos con TxtLog:

Redefiniendo TxtLog

Redefiniendo TxtLog

Ahora las nuevas clases “calculadoras de plazos”:

Implementaciones de ICalculadorPlazosTarea

Implementaciones de ICalculadorPlazosTarea

Bien, por último solo resta eliminar las dependencias (o mejor dicho invertirlas) de la clase ProcesoAutorizacionTarea:

Aplicando DIP a la clase ProcesoAutorizacionTarea

Aplicando DIP a la clase ProcesoAutorizacionTarea

Como podemos ver  el punto A del principio estaría resuelto con la intrdocción de ILog, ya que ahora tanto ProcesoAutorizacionTarea como TxtLog dependen de una abstracción (es decir, de ILog). También estaríamos cumpliendo del punto B, ya que por ejemplo, los métodos para calcular plazos dependen de la abstracción ICalculadorPlazosTarea y no de la clase ProcesoAutorizacionTarea. Espero que les sea de utilidad!

Anuncios

ASP.NET MVC 3 y Structure Map

Como ya hemos hablado en otros post, una de las características que nos permiten mejorar el código de nuestros desarrollos es la utilización de patrones de diseño. Uno de esos patrones es la Inyección de Dependencias que consiste en suministrar objetos a una clase en lugar de ser la propia clase quien cree el objeto.

En este post voy a mostrarles un framework llamado Structure Map que nos permite aplicar este patrón en nuestros proyectos .NET y la forma de integrarlo al soporte de IoC que provee ASP.NET MVC 3.

Structure Map es un framework para .NET que nos permite trabajar con Inyección de Dependencias e Inversión de Control.

El primer paso sera agregar las referencias a la librería de Structure Map. Para ello vamos a instalarlas utilizando Nuget:

Agregando la librería Structure Map

Agregando la librería Structure Map

Es importante recordar que la pieza central respecto al soporte de IoC que provee ASP.NET MVC 3 es la interfaz IDependencyResolver que nos permite “conectar” distintos motores de IoC con tan solo implementarla en una clase y luego registrarla.

En nuestro ejemplo vamos a crear nuestro propio Dependecy Resolver que va a ser manejado con Structure Map. Para ellos vamos a crear la clase StructureMapDependencyResolver que, como dijimos anteriormente, implementará IDependencyResolver:

1: public class StructureMapDependencyResolver : IDependencyResolver
2: {
3:     private IContainer container;
4:
5:     public StructureMapDependencyResolver(IContainer container)
6:     {
7:         this.container = container;
8:     }
9:
10:     public object GetService(Type serviceType)
11:     {
12:         if (serviceType.IsAbstract || serviceType.IsInterface)
13:         {
14:             return this.container.TryGetInstance(serviceType);
15:         }
16:         else
17:         {
18:             return this.container.GetInstance(serviceType);
19:         }
20:     }
21:
22:     public IEnumerable<object> GetServices(Type serviceType)
23:     {
24:         return this.container.GetAllInstances<object>()
25:             .Where(s => s.GetType() == serviceType);
26:     }
27: }

Lo que hicimos aquí fue implementar los siguiente métodos:

En ambos métodos hemos utilizado el contedor IContainer (que nos provee la librería Structure Map) cuya finalidad es la de registrar y resolver las dependencias que hayamos definido.

Bien, ahora vamos a crear una interfaz bien simple, la cual denominaremos IMessage:
1: public interface IMessage
2: {
3:     string GetMessage();
4: }

Y dos implementaciones bien sencillas de la misma, la primera la llamaremos HelloMessage:

1: public class HelloMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Buenos días!" ;
6:     }
7: }

Y la segunda ByeMessage:

1: public class ByeMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Hasta mañana!" ;
6:     }
7: }

Llego el momento de registrar a nuestro “resolvedor(?) de dependencias”  🙂 y para ello debemos agregar las siguientes lineas en el archivo global.asax:

1: public class MvcApplication : System.Web.HttpApplication
2: {
3:     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4:     {
5:         filters.Add(new HandleErrorAttribute());
6:     }
7:
8:     public static void RegisterRoutes(RouteCollection routes)
9:     {
10:         routes.IgnoreRoute("{resource}.axd/{*pathInfo}" );
11:
12:         routes.MapRoute(
13:             "Default", // Route name
14:             "{controller}/{action}/{id}", // URL with parameters
15:             new { controller = "Home" , action = "Index" } 
16:         );
17:
18:     }
19:
20:     protected void Application_Start()
21:     {
22:         AreaRegistration .RegisterAllAreas();
23:
24:         RegisterGlobalFilters(GlobalFilters.Filters);
25:         RegisterRoutes(RouteTable.Routes);
26:
27:         InitializeContainer();
28:     }
29:
30:     public void InitializeContainer()
31:     {
32:         var c = InitContainer();
33:         DependencyResolver.SetResolver(new StructureMapDependencyResolver(c));
34:     }
35:
36:     private static IContainer InitContainer()
37:     {
38:         var container = new Container();
39:
40:         container.Configure(s => s.For<IMessage>().Use<HelloMessage>());
41:
42:         return container;
43:     }
44: }

Dentro del método Application_Start() invocamos un nuevo método llamado InitializeContainer() en el cual vamos a registrar StructureMapDependencyResolver como el encargado de resolver las dependencias. Previamente a este paso hemos creamos el método InitContainer() en el cual hemos creado un objeto Container al cual le fuimos configurando el mapeo entre interfaces y clases que sera utilizado para poder resolver las dependencias (en el ejemplo solo es uno y es el de IMessage).

Es hora de crear el controlador HomeController cuyo constructor recibirá como parámetro un IMessage el cual será “inyectado” cada vez que sea instanciado (de lo cual ya no debemos preocuparnos gracias a IDependencyResolver). También vamos a definir un método de acción Index:

1: public class HomeController : Controller
2: {
3:     private IMessage MessageService { get ; set ; }
4:
5:     public HomeController(IMessage service)
6:     {
7:         this .MessageService = service;
8:     }
9:
10:     public ActionResult Index()
11:     {
12:         ViewBag.Message = MessageService.GetMessage();
13:
14:         return View();
15:     }
16: }

Ejecutamos y veremos que el servicio instancia es el que hemos definido al momento de crear el contenedor, en este caso HelloMessage:

Resultado obtenido de HelloMessage

Resultado obtenido de HelloMessage

Ahora modificamos el contenedor para instanciar el servicio ByeMessage en la interfaces IMessage:

1: private static IContainer InitContainer()
2: {
3:     var container = new Container();
4:
5:     container.Configure(s => s.For<IMessage>().Use<ByeMessage>());
6:
7:     return container;
8: }

Ejecutamos y verificamos que se invoco el servicio que definimos:

Resultado obtenido con ByeMessage

Resultado obtenido con ByeMessage

De más esta decir, que esto simplifica y mejora el código de nuestros desarrollos, ya que en el caso de que debamos modificar la referencias a nuestros servicios, y si estos mantienen el contrato, solo debemos modificar una sola línea de nuestro proyecto, y es el mapeo entre interfaz y clase que hemos configurado en el contenedor de dependencias.

Quienes quieran descargar el proyecto pueden hacerlo desde acá: MvcAndStructureMap.rar.

Espero que les sea de utilidad.

Implementando IoC en ASP.NET MVC 2 con Castle Windsor

En un post anterior hablamos sobre los beneficios de aplicar el patrón IoC en nuestros proyectos y vimos un breve ejemplo utilizando Unity de la gente de Patterns & Practices. Además comentamos que existen diferentes frameworks que nos facilitan estas tareas, uno de ellos es Castle Windsor y es el que vamos a utilizar en este caso.

Castle Project

Castle Project

En este post vamos a explicar cómo configurar IoC utilizando este framework en una aplicación web ASP.NET MVC 2.

El primer paso será descargar desde la página oficial del proyecto Castle las librerías Windsor 2.1link de la descarga.

El siguiente paso será crear una aplicación ASP.NET MVC 2 y agregar las siguientes referencias a nuestro proyecto:  Castle.Core.dll, Castle.MicroKernel.dll, Castle.Windsor.dll.

Referencias

Referencias

Para seguir con el ejemplo del post inicial, vamos a crear una interfaz denominada IRedSocialService y dos servicios que la implementen (por ejemplo TwitterService y FacebookService). La definición de la interfaz podría ser la siguiente:

public interface IRedSocialService
{
    IEnumerable ObtenerContactos();
}

La implementación de ambos servicios se las dejo a ustedes 🙂 .

A continuación vamos a configurar nuestras dependencias utilizando Windsor Container. Para ello lo que vamos hacer es realizar algunas modificaciones en nuestro archivo de configuración Web.config y separar las configuraciones propias del contenedor en otro archivo de configuración aparte que vamos a crear y llamar Castle.config.

La estructura del proyecto sería más o menos la siguiente:

Estructura proyecto

Estructura proyecto

Al archivo web.config vamos a agregarle lo siguiente:

<configuration>
<configSections>
...
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>

<castle configSource="Castle.config"></castle>
 …
</configuration>

Qué estuvimos haciendo? En primer lugar indicando que la sección castle será utilizada por CastleSectionHandler y que es encuentra en el assemblie Castle.Windsor. En segundo lugar estamos indicando que la sección castle se encuentra dentro del archivo castle.config y que vamos a configurar a continuación.

Al archivo castle.config vamos a agregar lo siguiente:

<castle>
<components>
<component id="ServicioRedSocial"
                    type="Castle.Windsor.Logica.TwitterService, Castle.Windsor.Logica"
                    service="Castle.Windsor.Logica.IRedSocialService, Castle.Windsor.Logica" />
</components>
</castle>

Qué estuvimos haciendo? Estuvimos registrando nuestro primer elemento del contenedor. Vamos a explicar cada tag por parte:

  • id: nombre con el que queremos identificar ese elemento en particular.
  • service: la interfaz sobre la cual vamos hacer las inyecciones.
  • type: el tipo concreto que queremos que el contenedor devuelva como implementación de la interfaz definida.

Teniendo en cuenta la configuración actual, cuando solicitemos una instancia de IRedSocialService deberíamos obtener un objeto TwitterService. Pero ojo, aún falta para que esto suceda…

Ahora es turno de trabajar con nuestro controlador que llamaremos RedSocialController, y en donde vamos a definir nuestro contenedor y nuestro servicio de la siguiente manera:

private WindsorContainer contenedor;
private IRedSocialService servicio;

Ahora vamos a trabajar sobre el constructor del controlador y la acción Index :

public class RedSocialController : Controller
{
    private WindsorContainer contenedor;
    private IRedSocialService servicio;

    public RedSocialController()
    {
        this.contenedor = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        this.servicio = contenedor.Resolve<IRedSocialService>();
    }

    public ActionResult Index()
    {
        IEnumerable contactos = servicio.ObtenerContactos();
        return View(contactos);
    }
}

Dentro del constructor del controlador creamos nuestro contenedor, indicándole que la sección castle del archivo de configuración tiene las configuraciones correspondientes. Luego seteamos nuestro servicio, pidiendo al contenedor que nos devuelva la instancia que hayamos configurado. Finalmente vamos a tener disponible nuestro servicio en cada una de las acciones de RedSocialController.

Ejecutamos y listo!

Ejemplo IoC

Ejemplo IoC

Si ahora deseamos recuperar los contactos de otra red social, solo deberemos modificar nuestro archivo de configuración y todo solucionado!

Pero porqué quedarse acá? Porqué no aprovechar algunas de las características de ASP.NET MVC y automatizar aún más nuestras inyecciones?… Comencemos entonces!

La idea ahora es hacer las inyecciones sobre los parámetros del constructor de los controladores, y evitar tener que crear en cada controlador el contenedor y luego setear los servicios. Pero cómo podemos hacer esto? …  ASP.Net MVC al crear un controlador utiliza una factory, una instancia de la clase DefaultControllerFactory que requiere que los controladores tengan el constructor por defecto. Cómo esto no nos sirve, ya que la idea es tener constructores con parámetros, podemos crear nuestra propia factory y luego especificarle a MVC que las utilice (tengamos en cuenta que deberá heredar de DefaultControllerFactory).

Entonces vamos a crear nuestra propia factory que se va a encargar de realizar las inyecciones de dependencias sobre los parámetros de nuestros controladores (y por nosotros :)). Para esto vamos a crear una clase denominada WindsorControllerFactory.

Veamos cómo queda nuestra factory:

public class WindsorControllerFactory : DefaultControllerFactory
{
    WindsorContainer container;

    public WindsorControllerFactory()
    {
        container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                                     where typeof(IController).IsAssignableFrom(t)
                                     select t;

        foreach (Type t in controllerTypes)
            container.AddComponentLifeStyle(t.FullName, t,LifestyleType.Transient);
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
            return null;

        return (IController)container.Resolve(controllerType);
    }
}

Como vemos debemos sobre-escribir el método GetControllerInstance e inyectar las dependencias al momento de devolver el controlador – esto en tiempo de ejecución.

Finalmente debemos indicarle a MVC que utilice nuestra controller factory, para eso agregamos en nuestro archivo global.asax la siguiente línea dentro del método Application_Start():

ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());

Finalmente volvemos a redefinir nuestro controlador de la siguiente forma:

public class RedSocialController : Controller
{
    private IRedSocialService servicio;

    public RedSocialController(IRedSocialService servicio)
    {
        this.servicio = servicio;
    }

    public ActionResult Index()
    {
        IEnumerable contactos = servicio.ObtenerContactos();
        return View(contactos);
    }
}

A diferencia del controlador anterior, este tiene definido como parámetros del constructor el tipo de interfaz que vamos a utilizar en el servicio, la cuál es inyectada por nuestra factory al momento de inicializarse el controller. También podemos ver que no es necesario crear el contenedor y setear nuestro servicio, lindo no!?

Inversión de Control e Inyección de dependencia

En esta entrada voy a comentarles el uso de dos patrones que básicamente lo que intentan es evitar que una clase que sufre dependencias de otras, no sea la responsable de crearse a sí misma o no de recibir otras clases cómo parámetros.

Para poder entender estos patrones vamos a imaginar que estamos trabajando en un proyecto, cuyo objetivo es leer contenido desde una red social: por ejemplo desde Twitter o Facebook. Lo primero que podríamos hacer es crear una clase por cada red social que necesitemos consultar.

Para ello vamos a crear dos clases: FacebookServices y TwitterServices y en cada una de ellas vamos a agregar un método que recupera la lista de contactos del usuario:

List<Contactos> ObtenerContactos(string usuario, string password)

Además vamos a tener una tercer clase que se va a encargar de centralizar la lógica del servicio: RedSocialService. Esta clase va a tener como parámetro del constructor el servicio de la red social que voy a utilizar:

 public class RedSocialService
 {
     public FacebookServices  Service { get; set; }

     public RedSocialService(FacebookServices service)
     {
         this.Service = service;
     }
 }

Uso directo de las clases (nivel de máximo acoplamiento)

Primer problema de dependencia que encontramos: qué servicio voy a utilizar para recuperar los usuarios?, podría obtenerlos de cualquiera de las redes sociales que tengamos definidas como servicio. Por ejemplo podríamos hacer:

FacebookServices servicioFacebook = new FacebookServices();
RedSocialService servicio = new RedSocialService (servicioFacebook);

var contactos = servicio.ObtenerContactos(usuario, password);

En este caso recuperaríamos los contactos desde que tiene en Facebook. Ahora supongamos que queremos entregar esta aplicación a un cliente que no posee una cuenta en este red social y desea obtener sus contactos desde Twitter por ejemplo, entonces deberíamos modificar todas las instancias a este servicio por el servicio de esta otra ubicación, además de modificar el constructor de la clase RedSocialService. Finalmente generar una nueva aplicación por cada tipo de red social que nos soliciten y tener de esta forma múltiples ejecutables.

Esto no es nada divertido y óptimo. podemos ver ahora la gran dependencia que hay en nuestro código y los problemas que está representa.

Uso de interfaces (nivel de acoplamiento medio)

Para evitar esta fuerte dependencia, podríamos hacer uso de las interfaces. Para esto vamos a crear la interfaz IRedSocialService y vamos a agregarle la firma:

 List<Contactos> ObtenerContactos(string usuario, string password);

Y hacer que tanto FacebookServices como TwitterServices implementen de ella.

Luego modificamos el constructor de RedSocialService para que reciba como parámetro un servicio que implemente IRedSocialService.

 public class RedSocialService
 {
     public IRedSocialService Service { get; set; }

     public RedSocialService(IRedSocialService service)
     {
         this.Service = service;
     }
 }

Finalmente nuestra llamada:

IRedSocialService servicio = new FacebookServices();

RedSocialService miServicio = new RedSocialService(servicio);
var contactos = servicio.ObtenerContactos(usuario, password);

Como podemos ver el nivel de dependencia disminuyo considerablemente. Ahora ante un cambio, solo debemos modificar nuestras instancias de IRedSocialService . Si bien mejoramos nuestro código, aún sigue existiendo dependencia.

Patrón Factory (nivel de acoplamiento bajo)

Este patrón lo que permite es delegar a otra clase la creación del servicio apropiado. Para esto vamos a crear una nueva clase a la que vamos a llamar RedSocialFactory. En ella vamos a crear un método que vamos a llamar ObtenerServicio , el cual tendrá como parámetro el nombre de la red social que usaremos y nos devolverá el servicio correspondiente y que por supuesto implementará IRedSocialService:

public static IRedSocialService ObtenerServicio(string nombreRedSocial)
{
    switch (nombreRedSocial)
    {
        case "Facebook":
             return new FacebookServices();
        case "Twitter":
              return new TwitterServices();
        default:
              throw new ArgumentOutOfRangeException("Red social no soportada.");
     }
}

Por lo tanto ahora podríamos definir dentro de un archivo de configuración o un archivo de recursos que red social vamos a utilizar en la aplicación, y hacer nuestra llamada de la siguiente forma:

IRedSocialService servicio = RedSocialFactory.ObtenerServicio(ConfigurationManager.AppSettings["RedSocial"]);

RedSocialService miServicio = new RedSocialService(servicio);
var contactos = miServicio.ObtenerContactos(usuario, password);

En este caso nos evitaremos entre otras cosas, generar un ejecutable por cada servicio, y al momento de entregar al cliente solo modificar el parámetro que corresponde a la red social. Además no deberemos modificar en nada el resto del código.

Inyección de dependencias (nivel de acomplamiento mínimo)

Basicamente IoC trabaja con el mismo principio de la Factory, solo que el mismo nos proporciona una forma de hacer esta tarea más sencilla y prolija, además de permitirnos realizar otras configuraciones.

Si bien existen muchísimos frameworks de IoC, como por ejemplo Castle, Spring o Ninject, nosotros vamos a utilizar Unity que nos proporciona Patterns & Practices.

Patterns & Practices

Patterns & Practices

Este framework nos brinda un contenedor, en el cual vamos a mapear nuestras clases a instancias, por lo tanto cuando solicitemos una instancia de cierto tipo, nos devolverá la clase que hemos definimos. Para esto en nuestro proyecto primero deberemos referenciar a:

using Microsoft.Practices.Unity;

Luego hacemos el mapeo entre la interfaz y clase:

IUnityContainer container = new UnityContainer();
container.RegisterType<IRedSocialService, FacebookServices>();

Finalmente pedimos al contenedor que se encargue de resolver y recuperar la clase para la instancia solicitada:

IRedSocialService servicio = container.Resolve<IRedSocialService>();

RedSocialService miServicio = new RedSocialService(servicio);
var contactos = miServicio.ObtenerContactos(usuario, password);

Pero hay mucho más y mejor :), supongamos que defino de esta forma al servicio:

RedSocialService servicio = container.Resolve<RedSocialService>();

Unity buscará si existe un mapeo para la clase RedSocialService, como no lo encuentra ya que no es una interfaz, buscará en los parámetros de su constructor, al ver que es del tipo IRedSocialService, entonces buscará si existe el mapeo de la misma, y si existe instanciara la clase al parámetro, es decir, inyectará los parámetros del constructor.

Espero que les sea de utilidad!