代码改变世界

巧用ViewState属性

2010-03-19 10:41  xiaosuo  阅读(265)  评论(0编辑  收藏  举报

当我在页面中使用ViewState ,通常是用一个属性表示,例如:

private int ViewState_UserID
{
    
get { return (int) ViewState["UserId"]; }
    
set { ViewState["UserId"= value; }
}

写这样一组代码感觉比较麻烦,如果能像下面这样简单地使用就好了。

[ViewStateProperty("UserID")]
protected int ViewState_UserID { getset;}

或者

[ViewStateProperty]
protected int ViewState_UserID { getset;}

这里介绍一种超级简单的方式去实现:使用Attribute。

第一步:创建BasePage 类,它继承System.Web.UI.Page。这里使用了Reflection和LINQ。

using System.Reflection;
using System.Linq;
public class BasePage : System.Web.UI.Page

第二步:在BasePage中使用一个内部类ViewStateProperty ,这个类继承Attribute 。用Attribute的目的是描述页面中哪个属性是viewstate属性。用这个属性来标识viewstate属性,因此它应该BasePage内部。 

代码
[AttributeUsage(AttributeTargets.Property)]
public class ViewStateProperty : Attribute
{
    
public string ViewStateName { getprivate set; }

    
internal ViewStateProperty(){
        
this.ViewStateName = string.Empty;
    }

    
public ViewStateProperty(string in_ViewStateName){
        
this.ViewStateName = in_ViewStateName;
    }
}

[AttributeUsage(AttributeTargets.Property)]意味着这个attribute 只对property类型可用。在public ViewStateProperty(string in_ViewStateName)中初始化ViewState 的名称。默认情况下,ViewState 的名字为空。如果你想在设置attribute的时候初始化ViewState的名字时,要将默认构造函数设置为私有的。

第三步:在BasePage中,创建一个ViewStateProperties变量来存储有ViewStateProperty标签的属性,在BasePage默认构造函数中初始化它们:

代码
private PropertyInfo[] ViewStateProperties;
protected BasePage() 
{
    
this.ViewStateProperties = GetType().GetProperties(
      BindingFlags.NonPublic 
| BindingFlags.Instance).Where(
      p 
=> p.GetCustomAttributes(typeof(ViewStateProperty), true).Length > 0).ToArray();
}

GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)通过反射获得所有的public 和protected属性 。Where(p=>p.GetCustomAttributes(typeof(ViewStateProperty), true).Length > 0)用来过滤有ViewStateProperty修饰的属性。

第四步: 在BasePage中重载LoadViewState 和SaveViewState方法

代码
protected override void LoadViewState(object savedState)
{
    
base.LoadViewState(savedState);
    
foreach (PropertyInfo property in ViewStateProperties)
    {
        ViewStateProperty[] attributes 
= (ViewStateProperty[])
          property.GetCustomAttributes(
typeof(ViewStateProperty), false);
        var LocalName 
= (string.Empty == attributes[0].ViewStateName) ? 
           property.Name : attributes[
0].ViewStateName;
        
if (ViewState[LocalName] != null)
            property.SetValue(
this, ViewState[LocalName], null);
    }
}

protected override object SaveViewState()
{
    
foreach (PropertyInfo property in ViewStateProperties)
    {
        ViewStateProperty[] attributes 
= (ViewStateProperty[])
          property.GetCustomAttributes(
typeof(ViewStateProperty), false);
        var LocalName 
= (string.Empty == attributes[0].ViewStateName)? 
          property.Name:attributes[
0].ViewStateName;
        ViewState[LocalName] 
= property.GetValue(thisnull);
    }
    
return base.SaveViewState();
}

目的是根据name设置viewstate值,这个name设置在ViewStateProperty标签上,加载ViewState的值,并赋值给有ViewStateProperty修饰的属性

使用它:

[ViewStateProperty("UserID")]
protected int ViewState_UserID { getset;}

 或者:

[ViewStateProperty]
protected int ViewState_UserID { getset;}

在第一个,设置一个名为UserID的ViewState,第二个,您设置名为ViewState_UserID的ViewState。

注意:要实现这样的属性,您不能将它们设置为私有的,因为 GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance) 不能返回private 属性,设置为protected足以满足我们的需要。

参考原文:http://www.cnblogs.com/zhuqil/archive/2010/01/30/ViewStateAttribute.html