地址:http://www.codeproject.com/KB/viewstate/ViewStateAttribute.aspx
背景
当我们在页面中创建一个ViewState,我们通常为ViewState创建一个属性,像这样:
{
get { return (int) ViewState["UserId"]; }
set { ViewState["UserId"] = value; }
}
你不觉得创建2个访问器有点令人讨厌吗? 能够使这个简单一些像一个自动的属性吗?像这样:
protected int ViewState_UserID { get; set;}
或者
protected int ViewState_UserID { get; set;}
代码详情
第一步:让我们创建一个从System.Web.UI.Page继承的BasePage,为一个更高层次的应用创建BasePage很普遍。我们将在这里使用反射和Linq。
using System.Linq;
public class BasePage : System.Web.UI.Page
第二步:在BasePage里创建一个继承自Attribute的内部类ViewStateProperty,Attribute类的目的是为了描述页面中的属性是viewstate属性。理论上,attribute的目标是viewstate属性,因此它应该在页面里。

public class ViewStateProperty : Attribute
{
public string ViewStateName { get; private set; }
internal ViewStateProperty(){
this.ViewStateName = string.Empty;
}
public ViewStateProperty(string in_ViewStateName){
this.ViewStateName = in_ViewStateName;
}
}
[AttributeUsage(AttributeTargets.Property)]意味着该attribute仅用于属性类型。public ViewStateProperty(string in_ViewStateName)构造器的目的是为了初始化ViewState名字。默认地,ViewState的名字为空。当设置attribute的时候,如果你想初始化ViewState名字,请使默认构造器为private。
第三步:在BasePage里,创建一个ViewStateProperties变量,存储那些有ViewStateProperty特征的属性,同时在BasePage里面的默认构造器初始化它们。

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特征(attribute)修饰的属性.
第四步:在BasePage里面覆盖(override)LoadViewState和
SaveViewState方法

{
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(this, null);
}
return base.SaveViewState();
}
我们的目标是建立在名称上,我们确定了ViewStateProperty特征或本身
由ViewStateProperty特征修饰的属性名称;加载ViewState的值到被ViewStateProperty特征修饰的属性上。
使用
在开始谈到的,很容易实现
protected int ViewState_UserID { get; set;}
或者
protected int ViewState_UserID { get; set;}
第一个,设置一个称作UserID的ViewState,第二个,设置一个称作ViewState_UserID的ViewState。
注释
实现这样的属性,你不能设置它们为private,因为GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)不会返回private属性,但是protected能够做到我们的目标。