【翻译】创建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 {  get set ;}

 

或者

[ViewStateProperty]
protected   int  ViewState_UserID {  get set ;}

 

 

代码详情

 

第一步:让我们创建一个从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 {  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里面的默认构造器初始化它们。 

代码
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( this null );
    }
    
return   base .SaveViewState();
}

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

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

 

使用

 

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

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

 

或者

ViewStateProperty]
protected   int  ViewState_UserID {  get set ;}

 

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

 

注释

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

你可能感兴趣的:(view)