65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ViewState 属性自动生成 ViewState 属性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (18投票s)

2010年1月28日

CPOL

2分钟阅读

viewsIcon

44895

自动 ViewState 属性。

引言

本文将演示如何通过属性实现自动 ViewState 属性。

背景

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

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

当您尝试创建几个时,您是否觉得有点无聊? 是否可以像自动属性一样简单? 像这样:

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

[ViewStateProperty]
protected int ViewState_UserID { get; set;}

是的,有一种简单的方法可以使用 Attribute 来实现它。

代码详情

第一步,让我们创建一个继承自 System.Web.UI.PageBasePage。 创建一个 BasePage 以获得更高的层次结构是很常见的。 我们将在此处使用反射和 LINQ。

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

第二步,在 BasePage 中创建一个继承自 Attribute 的内部类 ViewStateProperty。 此 Attribute 类的目的是描述页面中的哪个属性是 viewstate 属性。 从理论上讲,此属性针对 viewstate 属性,因此它应该位于 BasePage 内部。

[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)] 表示此属性仅适用于属性类型。 public ViewStateProperty(string in_ViewStateName) 构造函数用于初始化 ViewState 名称。 默认情况下,ViewState 名称为空。 如果您想在设置属性时初始化 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 属性修饰的属性。

第四步是覆盖 BasePage 中的 LoadViewStateSaveViewState 方法

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; 并将 ViewState 值加载到由 ViewStateProperty 属性修饰的属性。

使用它

正如开头提到的,它很容易实现。

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

[ViewStateProperty]
protected int ViewState_UserID { get; set;}

在第一个中,您设置一个名为 UserIDViewState,在第二个中,您设置一个名为 ViewState_UserIDViewState

注释

要实现这样的属性,您不能将它们设置为 private,因为 GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance) 不会返回 private 属性。 但是 protected 对于我们的目标来说已经足够了。

© . All rights reserved.