#if !(_WINDOWS_CE) && !(_SILVERLIGHT) && !(WINDOWS_PHONE) using System; using System.Diagnostics; using System.Threading; using System.Reflection; using System.Web; using System.Runtime.Remoting.Messaging; namespace Amib.Threading.Internal { #region CallerThreadContext class /// /// This class stores the caller call context in order to restore /// it when the work item is executed in the thread pool environment. /// internal class CallerThreadContext { #region Prepare reflection information // Cached type information. private static readonly MethodInfo getLogicalCallContextMethodInfo = typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo setLogicalCallContextMethodInfo = typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic); private static string HttpContextSlotName = GetHttpContextSlotName(); private static string GetHttpContextSlotName() { FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic); if (fi != null) { return (string) fi.GetValue(null); } return "HttpContext"; } #endregion #region Private fields private HttpContext _httpContext; private LogicalCallContext _callContext; #endregion /// /// Constructor /// private CallerThreadContext() { } public bool CapturedCallContext { get { return (null != _callContext); } } public bool CapturedHttpContext { get { return (null != _httpContext); } } /// /// Captures the current thread context /// /// public static CallerThreadContext Capture( bool captureCallContext, bool captureHttpContext) { Debug.Assert(captureCallContext || captureHttpContext); CallerThreadContext callerThreadContext = new CallerThreadContext(); // TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture() // Capture Call Context if(captureCallContext && (getLogicalCallContextMethodInfo != null)) { callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null); if (callerThreadContext._callContext != null) { callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone(); } } // Capture httpContext if (captureHttpContext && (null != HttpContext.Current)) { callerThreadContext._httpContext = HttpContext.Current; } return callerThreadContext; } /// /// Applies the thread context stored earlier /// /// public static void Apply(CallerThreadContext callerThreadContext) { if (null == callerThreadContext) { throw new ArgumentNullException("callerThreadContext"); } // Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run() // Restore call context if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null)) { setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext }); } // Restore HttpContext if (callerThreadContext._httpContext != null) { HttpContext.Current = callerThreadContext._httpContext; //CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext); } } } #endregion } #endif