2011-09-07 120 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