Inyección de propiedad en atributos

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

public class UserCanAccessArea : AuthorizeAttribute { readonly IPermissionService permissionService; public UserCanAccessArea() : this(DependencyResolver.Current.GetService()) { } 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 singleton, lo que significa que tengo los problemas descritos en mi pregunta anterior

Lo que me gustaría hacer es usar la inyección de propiedades, pero como mi atributo no es resuelto por Unity, no puedo encontrar la forma 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(new InjectionProperty("permissionService")); 

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

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

Debería evitar hacer la dependency injection en atributos por completo. El motivo de esto se explica en este artículo: Inyección de dependencia en atributos: ¡no lo hagas! . En resumen, el artículo explica que:

  • La inyección de constructores no es posible porque la creación de una instancia de atributo no puede ser interceptada; el CLR tiene el control
  • El uso de inyección de propiedad es frágil, ya que da como resultado el acoplamiento temporal , que debe evitarse.
  • La dependency injection en los atributos hace que sea imposible verificar la corrección de la configuración del contenedor.
  • Frameworks como los atributos de caché de MVC y Web API, lo que hace que sea muy fácil crear accidentalmente dependencias cautivas causando errores.

Tu tienes dos opciones aquí:

  1. Haga pasivos los atributos, dividiendo los datos (el atributo) de su comportamiento (el servicio) como se explica en el artículo al que se hace referencia y en este artículo relacionado de Mark Seemann.
  2. Convierte tus atributos en objetos humildes como se explica en esta respuesta . Esto significa tu:
    1. extraer toda la lógica del atributo en 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 llame al método del servicio. Es importante tener en cuenta que no se puede hacer la inyección del constructor, la inyección de propiedad y el servicio no se puede almacenar en el estado privado de los atributos (como ya ha notado).

Qué opción usar:

  • Use la opción 1 si está muy interesado en mantener su diseño limpio, 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.