剛剛接觸.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;
}
}
}
