2010-05-02 15 views
11

Tengo una aplicación web ASP.NET MVC que implementa un proveedor de membresía personalizado. El proveedor de membresía personalizado toma un UserRepository a su constructor que proporciona una interfaz entre el proveedor de membresía y NHibernate. El contenedor Ninject IoC proporciona UserRepository.Inyección de dependencia con un proveedor de membresía personalizado

Obviamente, sin embargo, esto no funciona cuando el proveedor es instanciado por .NET: el constructor sin parámetros no tiene un UserRepository y no puede crear uno (el UserRepository requiere que una sesión de NHibernate pase a su constructor), que luego significa que el proveedor no puede acceder a su almacén de datos. ¿Cómo puedo resolver mi dependencia de objeto?

Es probable que valga la pena señalar que se trata de una aplicación existente que se ha readaptado con Ninject. Anteriormente, utilicé constructores sin parámetros que podían crear sus dependencias requeridas junto con los constructores parametrizados para ayudar en las pruebas unitarias.

¿Alguna idea o me he arrinconado aquí?

Respuesta

5

Es posible que desee mantener el constructor sin parámetros, que inicializa los repositorios necesarios utilizando Ninject. Es posible que desee utilizar el Common Service Locator, por lo que no necesitará tener ninguna referencia a Ninject ni a su contenedor dentro de su proveedor personalizado. Parece que Ninject no tiene una implementación oficial de adaptador para CSL, pero escribir uno no debería ser difícil (verifique las otras implementaciones, como la de Windsor), y estoy seguro de que hay una implementación no oficial en algún lado.

+3

Ninject ha tenido un adaptador CSL oficial enero de 2010. –

+0

Todavía falta en la página de inicio de CSL (está incluida en la versión de NInject en su lugar) – SztupY

+1

"constructor, que inicializa los repositorios necesarios usando Ninject" - cuidado, si sus repositorios (o sus dependencias) están en el alcance Solicitud o Transitorio y cualquier El tipo de contexto de datos desechables entra en juego, usted terminará accediendo a un contexto de datos eliminados en todas las solicitudes excepto en la primera (porque no controla la duración de un Proveedor y ASP.NET la reutilizará en todas las solicitudes). Terminé obteniendo una instancia de repositorio del localizador cada vez que necesitaba llamar a uno cuando encontré este problema. –

-1

Tuve el mismo problema, lo resolví pasando los datos requeridos utilizando un ticket de autenticación al objeto de identidad.

Entonces no es necesario inyectar objetos en los proveedores de membresía.

En mi código de autenticación tengo

[NonAction] 
    private void SetAuthTicket(Member member, bool isPersistent) 
    { 
     HttpCookie cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName); 

     FormsAuthentication.SetAuthCookie(member.Email, isPersistent); 

     string userData = "|" + member.ID + "|" + member.Firstname + "|" + member.Lastname + member.Culture; 

     FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.Email, DateTime.UtcNow, DateTime.UtcNow.AddDays(7), isPersistent, userData); 

     string encryptedTicket = FormsAuthentication.Encrypt(ticket); 
     cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); 
     Response.Cookies.Add(cookie); 
    } 

Y en Global.asax

void Application_OnPostAuthenticateRequest(object sender, EventArgs e) 
    { 
     IPrincipal user = HttpContext.Current.User; 
     if (user.Identity.IsAuthenticated && user.Identity.AuthenticationType == "Forms") 
     { 
      FormsIdentity identity = user.Identity as FormsIdentity; 

      MyIdentity ai = new MyIdentity(identity.Ticket);    
      MyPrincipal p = new MyPrincipal(ai); 

      HttpContext.Current.User = p; 
      System.Threading.Thread.CurrentPrincipal = p; 

      if (!String.IsNullOrEmpty(ai.Culture)) 
      { 
       CultureInfo ci = new CultureInfo(ai.Culture); 
       System.Threading.Thread.CurrentThread.CurrentUICulture = ci; 
       System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); 
      } 
     } 
    } 

Y en la clase de Identidad que tienen propiedades MemberName, Firstname y Apellido que devuelven partes de la cadena de entradas.

+0

Por favor, ¿podría entrar en un poco más de detalle? ¿Cómo podría, por ejemplo, anular la función CreateUser() en su escenario? ¿Estás diciendo que en mi caso tendría que pasar el objeto del repositorio en el ticket de autenticación? – alastairs

+0

En lugar de pasar el ID de usuario del pase de depósito –

+0

¿qué? Estoy de acuerdo con @alastairs, ¿cómo se crean usuarios y otras cosas sin un repositorio? – mare

4

Dado que la colección de miembros y la instancia MemberShip.Provider se crean antes de que Ninject pueda instanciarlos, debe realizar la activación posterior a la creación en el objeto. Si marca sus dependencias con [Inyectar] para sus propiedades en su clase de proveedor, puede llamar a kernel.Inject (MemberShip.Provider) - esto asignará todas las dependencias a sus propiedades.

respuesta
+0

Suena bien; Lo resolví con el CSL, pero podría valer la pena volver a visitarlo para eliminar la dependencia adicional. – alastairs

+0

+1 Me gusta este método. – Pandincus

+2

¿A dónde llamarías kernel.Inject ...? – Matt

Cuestiones relacionadas