Pregunta

Hace unos días, tuve un problema con ASP.Net roscado. Yo quería tener un objeto único por cada solicitud Web. realmente necesito esto para mi unidad de trabajo. Yo quería crear una instancia de una unidad de trabajo por solicitud web para que aplicación identidad es válida a través de la solicitud. De esta manera yo podría utilizar un COI para inyectar mi propia IUnitOfWork a mis clases de repositorios de forma transparente, y que podía utilizar la misma instancia para consultar y luego actualizar mis entidades.

Desde que estoy usando la Unidad, por error me utilizaron PerThreadLifeTimeManager. Pronto me di cuenta de que ASP.Net modelo de hilos no es compatible con lo que quiero lograr. Básicamente se utiliza un conjunto de subprocesos y recicla las discusiones, y que hace que yo reciba una UnitOfWork por hilo !! Sin embargo, lo que quería era una unidad de trabajo por cada solicitud web.

Un poco de google me este gran post . Eso fue exactamente lo que quería; excepto por la parte de unidad que era muy fácil de lograr.

Esta es mi aplicación para PerCallContextLifeTimeManager por la unidad:

public class PerCallContextLifeTimeManager : LifetimeManager
{
    private const string Key = "SingletonPerCallContext";

    public override object GetValue()
    {
        return CallContext.GetData(Key);
    }

    public override void SetValue(object newValue)
    {
        CallContext.SetData(Key, newValue);
    }

    public override void RemoveValue()
    {
    }
}

Y, por supuesto Lo utilizo para registrar mi unidad de trabajo con un código similar al siguiente:

unityContainer
            .RegisterType<IUnitOfWork, MyDataContext>(
            new PerCallContextLifeTimeManager(),
            new InjectionConstructor());

Espero que salva a alguien un poco de tiempo.

¿Fue útil?

Solución

solución Neat, pero cada instancia de LifetimeManager debe utilizar una clave única en lugar de una constante:

private string _key = string.Format("PerCallContextLifeTimeManager_{0}", Guid.NewGuid());

De lo contrario, si usted tiene más de un objeto registrado con PerCallContextLifeTimeManager, están compartiendo la misma clave para acceder CallContext, y no hará que su objeto esperado regreso.

También vale la pena implementar RemoveValue para asegurar los objetos se limpian:

public override void RemoveValue()
{
     CallContext.FreeNamedDataSlot(_key);
}

Otros consejos

Si bien esto está muy bien llamar a este PerCallContextLifeTimeManager, estoy bastante seguro de que esto es no "seguro" para ser considerado un ASP.Net LifeTimeManager Por petición.

Si ASP.Net hace su hilo de intercambio, entonces el único tomada a través de la nueva hilo a través CallContext es el HttpContext actual - se habrá ido para cualquier otra cosa que almacene en CallContext. Esto significa que en situaciones de carga el código anterior podría tener resultados no deseados - y me imagino que sería un verdadero dolor de cabeza para rastrear qué

La única forma "segura" de hacerlo es con HttpContext.Current.Items, o hacer algo como:

public class PerCallContextOrRequestLifeTimeManager : LifetimeManager
{
    private string _key = string.Format("PerCallContextOrRequestLifeTimeManager_{0}", Guid.NewGuid());

    public override object GetValue()
    {
      if(HttpContext.Current != null)
        return GetFromHttpContext();
      else
        return GetFromCallContext();
    }

    public override void SetValue(object newValue)
    {
      if(HttpContext.Current != null)
        return SetInHttpContext();
      else
        return SetInCallContext();
    }

    public override void RemoveValue()
    {
    }
}

Obviamente, esto significa tomar las dependencias de System.Web: - (

Mucho más información sobre esta disponible en:

http://piers7.blogspot.com/2005/11/ threadstatic-CallContext-and_02.html

Gracias por su contribución,

Sin embargo, la propuesta de ejecución pregunta tiene dos inconvenientes, uno de los cuales es un error grave como ya se ha dicho por Steven Robbins en su respuesta y Miqueas Zoltu en un comentario .

  1. Contexto de llamadas no está garantizada para ser preservada por Asp.Net para una sola petición. Bajo carga, se puede cambiar a otro, causando ejecución propuesto para romper.
  2. No manejar la liberación de dependencias en el extremo de demanda.

En la actualidad, el paquete Unity.Mvc Nuget suministra una PerRequestLifetimeManager para hacer el trabajo. No se olvide de registrar su UnityPerRequestHttpModule asociado en el código de arranque de otro modo la liberación de dependencias no serán tratados bien.

Uso de bootstrapping

DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

o en system.webServer/modules web.config

<add name="UnityPerRequestHttpModule" type="Microsoft.Practices.Unity.Mvc.UnityPerRequestHttpModule, Microsoft.Practices.Unity.Mvc" preCondition="managedHandler" />

Parece su implementación actual también es adecuado para los formularios web. Y ni siquiera dependen de la MVC. Por desgracia, su montaje hace, debido a algunas otras clases que contiene.

Tenga cuidado, en caso de que utilice algún módulo personalizado http usando sus dependencias resueltas, pueden estar ya dispuestos en el módulo de EndRequest. Depende de orden de ejecución del módulo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top