2011-09-07 118 views
1

我很確定前段時間我看到了很好的東西(可能在企業庫中,不確定),但我現在只是無法谷歌 - 泛型變量包裝通過將它存儲在會話中使其持久化。用法是這樣的:會話持久性的變量包裝

Persistent< string > Name {get;set;}

// reguest 1.

Name = "A"; // in fact storing to session.. maybe Name.Value = "A" is necessary, not sure if implicit cast can be done here

// reguest 2.

return Name; // returns string "A", implicit conversion

當然

,我會實現我自己已經問過,但我想不出什麼好(一致和快速)的方法來確定變量會話密鑰(如何確保,我將獲得年齡爲每次名稱相同,但不同的,你知道..)

感謝名單, 羅馬

+0

你只是想創建一個會話包裝對象,是否正確? – Tejs

回答

2

如果你打算做一個自定義會話包裝,我會建議使用表達式來確保你的魔法字符串不會過時。

public int SomeProperty 
{ 
    get { return GetValueFor(x => x.SomeProperty); } 
    set { SetValueFor(x => x.SomeProperty, value); } 
} 

protected T GetValueFor<T>(Expression<Func<ThisClass, T>> propertySelector) 
{ 
    string propertyName = // Get Value from expression.. to loo long to post here 

    return (T)_session[propertyName]; 
} 

protected SetValueFor<T>(Expression<Func<ThisClass, T>> propertySelector, object value) 
{ 
    string propertyName = // Get value from expression 

    _session[propertyName] = value; 
} 

這樣一來,所有的屬性都只是映射會話對象在一個強類型的方式,如果你曾經重構,你不擔心魔術字符串。

+1

並且不要忘記確保會話密鑰包含某些內容以消除「 ThisClassInstance1.SomeProperty','ThatClassInstance1.SomeProperty','ThatClassInstance2.SomeProperty','ThisClassInstanceN.SomeProperty'等等 – LukeH

1

東西沿着這些路線:

private int CustomerID 
{ 
    get 
    { 
     if(Session["CustomerID"] != null) 
      return Convert.ToInt32(Session["CustomerID"]); 
     else 
      return 0; 
    } 
    set { Session["CustomerID"] = value; } 
} 

編輯:

另一種可能是這樣的:

public class Persist<T> 
{ 
    private string ObjectName; 

    public Persist(string Name) 
    { 
     ObjectName = Name; 
    } 

    public T Get() 
    { 
     return (T)(HttpContext.Current.Session[ObjectName]); 
    } 

    public void Set(T value) 
    { 
     HttpContext.Current.Session[ObjectName] = value; 
    } 
} 

這顯示包裹成一個簡單的Singleton類。

public class SV 
{ 
    private static readonly SV instance = new SV(); 

    public Persist<DateTime> FiscalDate; 
    public Persist<decimal> Revenue; 

    private SV() 
    { 
     FiscalDate = new Persist<DateTime>("FiscalDate"); 
     Revenue = new Persist<decimal>("Revenue"); 
    } 

    public static SV Instance 
    { 
     get 
     { 
     return instance; 
     } 
    } 
} 

不幸的是,使用有點羅嗦。

protected void Page_Load(object sender, EventArgs e) 
{ 
    if(!Page.IsPostBack) 
    { 
     SV.Instance.Revenue.Set(1234567890M); 
     SV.Instance.FiscalDate.Set(new DateTime(2011, 3, 15)); 
    } 
} 

protected void Button1_Click(object sender, EventArgs e) 
{ 
    DateTime when = SV.Instance.FiscalDate.Get(); 
    decimal amount = SV.Instance.Revenue.Get(); 
} 
+0

是的,當然,這是我想封裝的微不足道的解決方案,因爲我將有許多變量與此行爲,並且我喜歡事情DRY – rouen

-1

我想你可以做到這一點的一種方法是:

public class Persistent<T> 
{ 
    private readonly string _sessionKey; 
    private static readonly bool _valueType; 

    static Persistent() 
    { 
     _valueType = typeof(T).IsValueType; 
    } 

    public Persistent(T value = default(T)) 
    { 
     _sessionKey = Guid.NewGuid().ToString(); 
     SetValue(value); 
    } 

    private void SetValue(T value) 
    { 
     var item = (_valueType) 
      ? new PersistentWrapper { Value = value } 
      : (object)value; 

     HttpContext.Current.Session[_sessionKey] = item; 
    } 

    private T GetValue() 
    { 
     object item = HttpContext.Current.Session[_sessionKey]; 
     if (item != null) 
     { 
      if (_valueType) return ((PersistentWrapper)item).Value; 

      return (T)item; 
     } 

     return default(T); 
    } 

    [Serializable] 
    private class PersistentWrapper 
    { 
     public T Value { get; set; } 
    } 

    public static implicit operator T(Persistent<T> value) 
    { 
     if (value == null) return default(T); 
     return value.GetValue(); 
    } 

    public static implicit operator Persistent<T>(T value) 
    { 
     return new Persistent<T>(value); 
    } 
} 

這可能是用作:

public class Person 
{ 
    public Persistent<string> Name { get; set; } 
    public Persistent<int> Age { get; set; } 
} 

的使用方式:

var person = new Person(); 
person.Name = "Matt"; 
person.Age = 27; 

雖然它只是感覺髒我...

+0

這個解決方案是錯誤的 - 每次創建實例時guid都會有所不同 - 對於每個請求..所以你不能檢索先前請求處理中存儲的值; – rouen

0

謝謝jim31415我和我的包裝器一樣會話以下,

internal class SessionHelper { 
    private void Set<T>(string key, T value) { 
     HttpContext.Current.Session[key] = value; 
    } 
    private T Get<T>(string key) { 
     return (T)HttpContext.Current.Session[key]; 
    } 

    public int MemberID { 
     get { return Get<int>("SK_MemberID"); } 
     set { Set<int>("SK_MemberID", value); } 
    } 
    public string MemberAccount { 
     get { return Get<string>("SK_MemberAccount"); } 
     set { Set<string>("SK_MemberAccount", value); } 
    } 
    public string MemberDisplayName { 
     get { return Get<string>("SK_MemberDisplayName"); } 
     set { Set<string>("SK_MemberDisplayName", value); } 
    } 
    public string MemberGuid { 
     get { return Get<string>("SK_MemberGuid"); } 
     set { Set<string>("SK_MemberGuid", value); } 
    } 
} 

隨着this thread,助手類可以用static關鍵字來聲明。

+1

好方法!消除錯誤傾向的轉換。但我會建議注入HttpContextBase以便能夠測試控制器或服務,如果在一個 –

+0

內使用SessionWrapper也許可以通過覆蓋'Set ()'和'Get ()'函數來實現,以便提供一個'SessionWrapper '進行測試。 – AechoLiu