В поисках универсального контекстно-ориентированного хранилища - PullRequest
5 голосов
/ 10 апреля 2009

Во-первых, я хотел бы, чтобы хранилище на основе контекста было единым для всей среды!

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

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

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

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

Обновление

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

Ответы [ 2 ]

2 голосов
/ 14 декабря 2010

Вот ссылка на (по крайней мере, часть) реализации контекста 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, я предполагаю, что вы хотите воспользоваться тем, что информация, связанная с логическим потоком, будет передаваться дочерним потокам, а не просто желать " Thread Safe "место для хранения информации. Таким образом, если бы вы установили (pr Push) AmbientActivity при запуске вашего приложения, а затем больше не выдвигали никаких действий, любые последующие потоки также были бы частью этой же деятельности, поскольку данные, хранящиеся в LogicalSetData, наследуются дочерними потоками.

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

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

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

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

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

0 голосов
/ 10 апреля 2009

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

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

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

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

...