using Microsoft.AspNetCore.Http; using System; using System.Linq.Expressions; using System.Reflection; using System.Threading; namespace Microsoft.AspNetCore.Http { public static class HttpContextLocal { private static Func _asyncLocalAccessor; private static Func _holderAccessor; private static Func _httpContextAccessor; /// /// 获取当前 HttpContext 对象 /// /// public static HttpContext Current() { var asyncLocal = (_asyncLocalAccessor ??= CreateAsyncLocalAccessor())(); if (asyncLocal == null) return null; var holder = (_holderAccessor ??= CreateHolderAccessor(asyncLocal))(asyncLocal); if (holder == null) return null; return (_httpContextAccessor ??= CreateHttpContextAccessor(holder))(holder); // 创建异步本地访问器 static Func CreateAsyncLocalAccessor() { var fieldInfo = typeof(HttpContextAccessor).GetField("_httpContextCurrent", BindingFlags.Static | BindingFlags.NonPublic); var field = Expression.Field(null, fieldInfo); return Expression.Lambda>(field).Compile(); } // 创建常驻 HttpContext 访问器 static Func CreateHolderAccessor(object asyncLocal) { var holderType = asyncLocal.GetType().GetGenericArguments()[0]; var method = typeof(AsyncLocal<>).MakeGenericType(holderType).GetProperty("Value").GetGetMethod(); var target = Expression.Parameter(typeof(object)); var convert = Expression.Convert(target, asyncLocal.GetType()); var getValue = Expression.Call(convert, method); return Expression.Lambda>(getValue, target).Compile(); } // 获取 HttpContext 访问器 static Func CreateHttpContextAccessor(object holder) { var target = Expression.Parameter(typeof(object)); var convert = Expression.Convert(target, holder.GetType()); var field = Expression.Field(convert, "Context"); var convertAsResult = Expression.Convert(field, typeof(HttpContext)); return Expression.Lambda>(convertAsResult, target).Compile(); } } } }