2009-04-09 4 views
5

Прежде всего, я хочу, чтобы хранилище на основе контекста было согласованным по всей структуре!Поиск одноразового хранилища на основе контекста

Сказав это, я ищу элегантное решение для обеспечения безопасности этих свойств в ASP.NET, WCF и любом другом многопоточном .NET-коде. Свойства расположены в некоторых помощниках трассировки нижнего уровня (они отображаются через методы, если вам интересно, почему они являются внутренними).

Я бы предпочел не иметь зависимости от ненужных сборок (например, System.Web и т. Д.). Я не хочу, чтобы кто-либо использовал этот код для настройки чего-либо. Я просто хочу, чтобы это сработало;) Возможно, это слишком высокий порядок, хотя ...

У кого-нибудь есть трюки в рукавах? (Я видел реализацию весны)

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; 
     } 
    } 

Update

безопасным я не имею в виду синхронизированы. Справочная информация по вопросу here

+0

Мне нечего предложить, но меня также интересует эта проблема. FWIW Я помню, что видел в каком-то исходном репозитории (возможно, Castle, NInject или NHibernate) несколько реализаций чего-то вроде IContext, которые, как я думаю, предназначены для DI'd в приложении. Каждая реализация IContext использовала другую технологию (CallContext, HttpContext, Thread.SetData и т. Д.). Я не знаю точно, как они были предназначены для использования, но моя первая мысль заключалась в том, что это было абстрактное «Контекст». Во всяком случае, я вижу, могу ли я найти то, что я нашел раньше, и опубликовать ссылку. Это может быть полезно. – wageoghe

ответ

0

Я не знаю, что использование CallContext - это правильный ход здесь, если желание просто обеспечить потокобезопасный доступ к вашим свойствам. Если это так, оператор блокировки - это все, что вам нужно.

Однако, вы должны быть уверены, что используете его .

С CallContext вы получите доступ к потокобезопасности, потому что у вас будут отдельные экземпляры CallContext, когда вызовы поступают на разные потоки (или разные магазины, скорее). Однако это очень отличается от доступа к потоку ресурсов.

Если вы хотите разделить одно и то же значение по нескольким потокам, то инструкция блокировки - это путь. В противном случае, если вам нужны определенные значения для каждого потока/вызова, используйте CallContext или используйте статические методы GetData/SetData в классе Thread или атрибут ThreadStatic (или любое количество механизмов хранения на основе потоков).

+0

Я не занимаюсь синхронизацией. Как вы сказали, у них много механизмов для хранения на основе контекста, а некоторые не работают в определенных ситуациях (то есть CallContext и ThreadStatic в ASP.NET), следовательно, мой вопрос. – jsw

2

Вот ссылка (по крайней мере, частично) «контекст» реализации NHibernate в:

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

Это мне не ясно, где именно и как это вступает в игру в контексте NHibernate. То есть, если бы я хотел сохранить некоторые значения в «контексте», я бы получил «контекст» из NHibernate и добавил мои значения? Я не использую NHibernate, поэтому я действительно не знаю.

Я полагаю, что вы могли бы сами убедиться и убедиться в этом, если такая реализация будет полезна для вас. По-видимому, идея заключалась бы в том, чтобы ввести желаемую реализацию, в зависимости от типа приложения (ASP.NET, WCF и т. Д.). Вероятно, это подразумевает некоторую конфигурацию (возможно, минимальную, если нужно использовать MEF для загрузки «интерфейса ICurrentSessionContext»).

Во всяком случае, я нашел эту идею интересной, когда я нашел его некоторое время назад при поиске информации о CallContext.SetData/GetData/LogicalSetData/LogicalGetData, Thread.SetData/GetData, [ThreadStatic] и т.д.

Кроме того, на основе использования вами CallContext.LogicalSetData, а не CallContext.SetData, я предположим, что вы хотите воспользоваться тем фактом, что информация, связанная с логическим потоком, будет распространяться на дочерние потоки, а не просто на «безопасное по потоку» место для хранения информации.Таким образом, если вы должны были установить (pr Push) AmbientActivity в своем приложении, а затем не нажимать никаких действий, любые последующие потоки также будут частью того же самого действия, поскольку данные, хранящиеся через LogicalSetData, наследуются дочерними потоками.

Если вы что-то узнали за это время, так как вы впервые задали этот вопрос, мне было бы очень интересно узнать об этом. Даже если вы этого не сделали, мне было бы интересно узнать, что вы делаете с контекстом.

На данный момент я работаю над сохранением некоторой информации о контексте для ведения журнала/трассировки (аналогично поддержке контекста Trace.CorrelationManager.ActivityId и Trace.CorrelationManager.LogicalOpertionStack и log4net/NLog). Я хотел бы сохранить некоторый контекст (текущее приложение, текущий экземпляр приложения, текущую активность (возможно, вложенную)) для использования в приложении или службе WCF. И я хочу распространять его «автоматически» через границы службы WCF. Это позволяет разрешить ведение журнальных операторов, зарегистрированных в центральном репозитории, клиентом/деятельностью/и т. Д. Мы могли бы запрашивать и коррелировать для всех операторов регистрации конкретным экземпляром конкретного приложения. Операторы протоколирования могут быть сгенерированы на клиенте или в одной или нескольких службах WCF.

Распространение WCF ActivityId необязательно для нас, потому что мы хотим распространять (или мы думаем, что делаем) больше, чем просто ActivityId. Кроме того, мы хотим распространять эту информацию от клиентов Silverlight до служб WCF, а Trace.CorrelationManager недоступен в Silverlight (по крайней мере, не в 4.0, возможно, что-то вроде этого будет доступно в будущем).

В настоящее время я создаю прототипы распространения нашей «контекстной» информации с помощью IClientMessageInspector и IDispatchMessageInspector. Похоже, он, вероятно, будет работать нормально для нас.

Что касается зависимости от System.Web, реализация NHibernate имеет «ReflectiveHttpContext», который использует отражение для доступа к HttpContext, поэтому не будет зависимости проекта от System.Web. Очевидно, что System.Web должен быть доступен, если приложение развернуто, если HttpContext настроен для использования.

Смежные вопросы