//----------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel { using System; using System.ServiceModel.Channels; using System.Threading; public sealed class OperationContextScope : IDisposable { [ThreadStatic] static OperationContextScope legacyCurrentScope; static AsyncLocal currentScope = new AsyncLocal(); OperationContext currentContext; bool disposed; readonly OperationContext originalContext = OperationContext.Current; readonly OperationContextScope originalScope = OperationContextScope.CurrentScope; readonly Thread thread = Thread.CurrentThread; public OperationContextScope(IContextChannel channel) { this.PushContext(new OperationContext(channel)); } public OperationContextScope(OperationContext context) { this.PushContext(context); } private static OperationContextScope CurrentScope { get { return ServiceModelAppSettings.DisableOperationContextAsyncFlow ? legacyCurrentScope : currentScope.Value; } set { if (ServiceModelAppSettings.DisableOperationContextAsyncFlow) { legacyCurrentScope = value; } else { currentScope.Value = value; } } } public void Dispose() { if (!this.disposed) { this.disposed = true; this.PopContext(); } } void PushContext(OperationContext context) { bool isAsyncFlowEnabled = OperationContext.ShouldUseAsyncLocalContext; this.currentContext = context; if (isAsyncFlowEnabled) { OperationContext.EnableAsyncFlow(this.currentContext); } CurrentScope = this; OperationContext.Current = this.currentContext; } void PopContext() { if (ServiceModelAppSettings.DisableOperationContextAsyncFlow && this.thread != Thread.CurrentThread) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInvalidContextScopeThread0))); if (CurrentScope != this) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxInterleavedContextScopes0))); if (OperationContext.Current != this.currentContext) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxContextModifiedInsideScope0))); CurrentScope = this.originalScope; OperationContext.Current = this.originalContext; if (this.currentContext != null) this.currentContext.SetClientReply(null, false); } } }