inyeccion dependencias c# asp.net-mvc authentication dependency-injection unity-container

inyeccion de dependencias c#



Inyección de dependencias en atributos (1)

Debe evitar hacer una inyección de dependencia en los atributos por completo. La razón de esto se explica en este artículo: Inyección de dependencias en atributos: ¡no lo hagas! . En resumen, el artículo explica que:

  • La inyección del constructor no es posible, porque la creación de una instancia de Atributo no puede ser interceptada; El CLR está en control.
  • El uso de la inyección de propiedades es frágil, ya que da como resultado un acoplamiento temporal , que debe evitarse.
  • La inyección de dependencia en los atributos hace que sea imposible verificar la corrección de la configuración del contenedor.
  • Los marcos como MVC y los atributos de caché de la API web, lo que hace que sea muy fácil crear accidentalmente dependencias cautivas que causan errores.

Tu tienes dos opciones aquí:

  1. Haga los atributos pasivos, dividiendo los datos (el atributo) de su comportamiento (el servicio) como se explica en el artículo referenciado y este artículo relacionado de Mark Seemann.
  2. Convierta sus atributos en objetos humildes como se explica en esta respuesta . Esto significa tu:
    1. extraer toda la lógica del atributo a un servicio personalizado que contenga todas las dependencias.
    2. Registre ese servicio en su contenedor.
    3. deje que el método del atributo ( AuthorizeCore en su caso) no haga nada más que resolver el servicio desde el localizador de servicios / DependencyResolver y llamar al método del servicio. Es importante tener en cuenta aquí que no puede realizar la inyección del constructor, la inyección de propiedades y el servicio no puede almacenarse en el estado privado de atributos (como ya lo notó).

Qué opción usar:

  • Use la opción 1 si está muy interesado en mantener limpio su diseño, o si tiene más de unos pocos atributos que necesita aplicar de esta manera, o si desea aplicar los atributos definidos en un ensamblaje que no depende de System.Web .Mvc.
  • Use la opción 2 de lo contrario.

Estoy tratando de inyectar una dependencia en un AuthorizeAttribute personalizado de la siguiente manera:

public class UserCanAccessArea : AuthorizeAttribute { readonly IPermissionService permissionService; public UserCanAccessArea() : this(DependencyResolver.Current.GetService<IPermissionService>()) { } public UserCanAccessArea(IPermissionService permissionService) { this.permissionService = permissionService; } protected override bool AuthorizeCore(HttpContextBase httpContext) { string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; bool isAuthorized = false; if (base.AuthorizeCore(httpContext)) isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); return isAuthorized; } }

Esto funciona pero parece resolverse como un singleton, lo que significa que obtengo los problemas descritos en mi pregunta anterior

Lo que me gustaría hacer es usar la inyección de propiedades, pero como Unity no resuelve mi atributo en sí mismo, no puedo encontrar una manera de configurar el contenedor para interceptar y resolver una propiedad. He probado lo siguiente:

public class UserCanAccessArea : AuthorizeAttribute { public IPermissionService permissionService { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; bool isAuthorized = false; if (base.AuthorizeCore(httpContext)) isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); return isAuthorized; } }

Envase:

container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService"));

Pero la propiedad siempre es nula en tiempo de ejecución.

¿Alguien ha logrado esto y si es así, tiene un ejemplo?