剛剛接觸.net web端的朋友都會被Session坑過,莫名其妙的不能讀取Session數據,后來知道原來有IRequiresSessionState這個接口,不繼承的就不能讀取Session里面的數據,知道這個以后呢,也不清楚里面具體是如何實現的。對此一直不甘心,於是查了各方面的資料終於模擬出來了。
在一般處理程序(ashx文件)里面有個一個(HttpContext Context),F12進入HttpContext 類你面你會發現它應該是用了單例的模式,里面有個 public static HttpContext Current { get; set; },應該是確定程序只有一個上下文。接下來可以找到public HttpSessionState Session { get; },這就是我們需要讀取Session。
廢話少說,首先說明用到了反射。我們來介紹下Type 類中的Type IsAssignableFrom(Type c);方法。假設A類繼承了B接口, Type a = typeof(A); Type b = typeof(B); 那么 a. IsAssignableFrom(b)的值為ture;這個可以判斷類是否繼承了IRequiresSessionState。這是第一步。
第二步就是找到當前訪問Session的類。這個就要用到StackTrace類,從名字上來看這個類是用來跟蹤代碼的。這里面要用到StackTrace 的GetFrame(index)方法和GetMethod(); 。GetFrame(index)這個是從調用的最里層往外層遍歷,它的返回值也是StackTrace 。是GetMethod() 返回值是MethodBase,而MethodBase的ReflectedType屬性可以得到當前類的Type。
原理都在上面的,下面的代碼是模擬過程。
using System; using System.Diagnostics; using System.Reflection; using System.Web.SessionState; namespace Ztest { public class Program: IRequiresSessionState { public static void Main(string[] args) { try { if (Test.Current.session == null) { Console.WriteLine("沒有繼承IRequiresSessionState"); } else { Console.WriteLine(Test.Current.session); } } catch (Exception ex) { } Console.ReadLine(); } } public class Test { private Test() { Type basetype = typeof(IRequiresSessionState); StackTrace trace = new StackTrace(); int i = 0; Type type; while (true) { ///找到外層第一個調用類 MethodBase methodName = trace.GetFrame(i).GetMethod(); type = methodName.ReflectedType; if (type != typeof(Test)) { break; } i++; } Boolean key = basetype.IsAssignableFrom(type); if (key) { session = _m; } else { session = null; } } private static Test _Current; private string _m = "當前類實現了IRequiresSessionState"; /// <summary> /// 模擬session /// </summary> public Object session { get; set; } public static Test Current { get { return get(); } set { Current = value; } } private static Test get() { if (_Current == null) { _Current = new Test(); } return _Current; } } }