2009-04-09 6 views
5

En primer lugar, ¡ojalá el almacenamiento basado en el contexto fuera coherente en todo el marco!En busca del almacenamiento basado en el contexto de un solo tamaño

Dicho esto, estoy buscando una solución elegante para hacer estas propiedades seguras en ASP.NET, WCF y cualquier otro código .NET multiproceso. Las propiedades están ubicadas en algunos ayudantes de seguimiento de bajo nivel (estos están expuestos a través de métodos si se está preguntando por qué son internos).

Preferiría no tener una dependencia en ensamblajes innecesarios (como System.Web, etc.). No quiero requerir que nadie use este código para configurar nada. Solo quiero que funcione;) Eso puede ser demasiado alto de una orden ...

¿Alguien tiene algún truco en la manga? (He visto la aplicación de la primavera)

internal static string CurrentInstance 
    { 
     get 
     { 
      return CallContext.LogicalGetData(currentInstanceSlotName) as string; 
     } 
     set 
     { 
      CallContext.LogicalSetData(currentInstanceSlotName, value); 
     } 
    } 

    internal static Stack<ActivityState> AmbientActivityId 
    { 
     get 
     { 
      Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>; 
      if (stack == null) 
      { 
       stack = new Stack<ActivityState>(); 
       CallContext.LogicalSetData(ambientActivityStateSlotName, stack); 
      } 

      return stack; 
     } 
    } 

actualización

Por seguro no me refiero sincronizada. Antecedentes sobre el problema here

+0

No tengo mucho para ofrecer, pero también estoy interesado en este tema. FWIW Recuerdo haber visto en algún repositorio de fuentes (probablemente Castle, NInject o NHibernate) varias implementaciones de algo así como IContext, que creo que están destinadas a ser incluidas en una aplicación. Cada implementación de IContext utilizaba una tecnología diferente (CallContext, HttpContext, Thread.SetData, etc.). No sé exactamente cómo iban a ser utilizados, pero mi primer pensamiento fue que era para abstraer "Contexto". De todos modos, puedo ver si puedo encontrar lo que encontré antes y publicar un enlace. Puede ser útil. – wageoghe

Respuesta

0

No sé si usar CallContext es el movimiento correcto aquí si lo que desea es simplemente proporcionar acceso seguro a sus propiedades. Si ese es el caso, la instrucción de bloqueo es todo lo que necesita.

Sin embargo, debe asegurarse de aplicarlo correctamente.

Con CallContext, obtendrá acceso a seguridad de subprocesos porque tendrá instancias separadas de CallContext cuando las llamadas entren en diferentes subprocesos (o en diferentes tiendas, más bien). Sin embargo, eso es muy diferente de hacer que el acceso a un recurso sea seguro para subprocesos.

Si desea compartir el mismo valor en varios hilos, la instrucción de bloqueo es el camino a seguir. De lo contrario, si desea valores específicos por subproceso/llamada, use CallContext o use los métodos estáticos GetData/SetData en la clase Thread o el atributo ThreadStatic (o cualquier cantidad de mecanismos de almacenamiento basados ​​en subprocesos).

+0

No me preocupa la sincronización. Como dijiste, hay muchos mecanismos para el almacenamiento basado en contexto y algunos no funcionan en ciertas situaciones (es decir, CallContext y ThreadStatic en ASP.NET) de ahí mi pregunta. – jsw

2

Aquí hay un enlace a (al menos en parte) de NHibernate aplicación "contexto":

https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/

No me queda claro exactamente dónde o cómo esto entra en juego en el contexto de NHibernate. Es decir, si quisiera almacenar algunos valores en "el contexto", ¿obtendré "el contexto" de NHibernate y agregaré mis valores? No uso NHibernate, entonces realmente no lo sé.

Supongo que podría mirar y determinar por usted mismo si este tipo de implementación le sería útil. Aparentemente, la idea sería inyectar la implementación deseada, dependiendo del tipo de aplicación (ASP.NET, WCF, etc.). Eso probablemente implica alguna configuración (tal vez mínima si uno fuera a usar MEF para cargar "la" interfaz ICurrentSessionContext).

En cualquier caso, he encontrado esta idea interesante cuando me encontré hace algún tiempo durante la búsqueda de información sobre CallContext.SetData/GetData/LogicalSetData/LogicalGetData, Thread.SetData/GetData, [ThreadStatic], etc.

También, basado en el uso de CallContext.LogicalSetData en lugar de CallContext.SetData, me Supongamos que quiere aprovechar el hecho de que la información asociada con el hilo lógico se propagará a los hilos hijo en lugar de simplemente querer un lugar "seguro para hilos" para almacenar información.Por lo tanto, si configurara (pr Push) AmbientActivity en el inicio de su aplicación y luego no realizara más actividades, los subprocesos posteriores también serían parte de esa misma actividad, ya que los datos almacenados a través de LogicalSetData son heredados por subprocesos secundarios.

Si ha aprendido algo mientras tanto, desde que hizo esta pregunta, estaría muy interesado en conocerla. Incluso si no lo hubiera hecho, me interesaría saber qué está haciendo con el contexto.

Por el momento, estoy trabajando para mantener cierta información de contexto para el registro/seguimiento (similar a Trace.CorrelationManager.ActivityId y Trace.CorrelationManager.LogicalOpertionStack y log4net/NLog context support). Me gustaría guardar un contexto (aplicación actual, instancia de aplicación actual, actividad actual (tal vez anidada)) para usar en una aplicación o servicio WCF Y quiero propagarlo "automáticamente" a través de los límites del servicio WCF. Esto es para permitir que las declaraciones de registro registradas en un repositorio central se correlacionen por cliente/actividad/etc. Podremos consultar y correlacionar todas las declaraciones de registro con una instancia específica de una aplicación específica. Las declaraciones de registro podrían haberse generado en el cliente o en uno o más servicios de WCF.

La propagación WCF de ActivityId no es necesariamente suficiente para nosotros porque queremos propagar (o creemos que lo hacemos) más que solo ActivityId. Además, queremos propagar esta información de los clientes de Silverlight a los servicios de WCF y Trace.CorrelationManager no está disponible en Silverlight (al menos no en 4.0, tal vez algo así estará disponible en el futuro).

Actualmente estoy prototipando la propagación de nuestra información de "contexto" usando IClientMessageInspector y IDispatchMessageInspector. Parece que probablemente funcione bien para nosotros.

Con respecto a una dependencia en System.Web, la implementación de NHibernate tiene un "ReflectiveHttpContext" que utiliza la reflexión para acceder al HttpContext, por lo que no habría una dependencia del proyecto en System.Web. Obviamente, System.Web debería estar disponible donde se implementa la aplicación si HttpContext está configurado para ser utilizado.

Cuestiones relacionadas