139 lines
3.7 KiB
C#
139 lines
3.7 KiB
C#
|
|
#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
|
|
|
|
/// <summary>
|
|
/// This class stores the caller call context in order to restore
|
|
/// it when the work item is executed in the thread pool environment.
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
private CallerThreadContext()
|
|
{
|
|
}
|
|
|
|
public bool CapturedCallContext
|
|
{
|
|
get
|
|
{
|
|
return (null != _callContext);
|
|
}
|
|
}
|
|
|
|
public bool CapturedHttpContext
|
|
{
|
|
get
|
|
{
|
|
return (null != _httpContext);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Captures the current thread context
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Applies the thread context stored earlier
|
|
/// </summary>
|
|
/// <param name="callerThreadContext"></param>
|
|
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
|