【翻译】创建ViewState特征的自动ViewState属性

地址:http://www.codeproject.com/KB/viewstate/ViewStateAttribute.aspx

 

背景

 

当我们在页面中创建一个ViewState,我们通常为ViewState创建一个属性,像这样:

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

 

 

你不觉得创建2个访问器有点令人讨厌吗? 能够使这个简单一些像一个自动的属性吗?像这样:

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

 

或者

[ViewStateProperty]
protected int ViewState_UserID { getset;}

 

 

代码详情

 

第一步:让我们创建一个从System.Web.UI.Page继承的BasePage,为一个更高层次的应用创建BasePage很普遍。我们将在这里使用反射和Linq。

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

 

 

第二步:在BasePage里创建一个继承自Attribute的内部类ViewStateProperty,Attribute类的目的是为了描述页面中的属性是viewstate属性。理论上,attribute的目标是viewstate属性,因此它应该在页面里。

代码
[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仅用于属性类型。public ViewStateProperty(string in_ViewStateName)构造器的目的是为了初始化ViewState名字。默认地,ViewState的名字为空。当设置attribute的时候,如果你想初始化ViewState名字,请使默认构造器为private

 

第三步:在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)的作用是在页面里通过反射获得所有publicprotected的属性。Where(p => p.GetCustomAttributes(typeof(ViewStateProperty), true).Length > 0)的作用是过滤那些被ViewStateProperty特征(attribute)修饰的属性.

 

第四步:在BasePage里面覆盖(override)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();
}

我们的目标是建立在名称上,我们确定了ViewStateProperty特征或本身

由ViewStateProperty特征修饰的属性名称;加载ViewState的值到被ViewStateProperty特征修饰的属性上。

 

使用

 

在开始谈到的,很容易实现

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

 

或者

ViewStateProperty]
protected int ViewState_UserID { getset;}

 

第一个,设置一个称作UserIDViewState,第二个,设置一个称作ViewState_UserID的ViewState。

 

注释

实现这样的属性,你不能设置它们为private,因为GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)不会返回private属性,但是protected能够做到我们的目标。

posted @ 2010-01-31 22:31  cry  阅读(321)  评论(0编辑  收藏  举报