asp.net webform页面状态自动加载和保存方法

作者:袖梨 2022-06-25
首先定义一个特性(attribute)。我会将这个特性放到需要自动加载和保存的属性上,以便将这些需要处理的属性从所有的页面属性中筛选出来,做进一步处理。这个特性的定义如下:
/// 
/// 自动保存属性. 能够实现字段或属性值的自动保存和加载. 该属性只在非静态字段或属性上才能生效.
/// 
/// 
/// 自动保存属性. 在页面类的属性上面加上该属性. 可以使得该字段或属性能够自动保存和自动加载.
/// 但是该属性必须是可序列化的. 否则抛出异常. 该属性只在非公有字段或属性上才能生效.
/// 
[attributeusage(attributetargets.property | attributetargets.field, allowmultiple = false, inherited = false)]
public class autosaveattribute : attribute
{
/// 
/// 初始化创建一个  类的实例. 使得具有该属性的类的属性具有自动保存的特性.
/// 
public autosaveattribute() { }
}
 
然后就是重写页面生命周期的某些事件,加入我们的处理代码。处理的过程为:㈠检索当前页面类型并将其需要处理的属性筛选出来(初始化过程);㈡将筛选出来的属性做保存或赋值操作(关键点)。
 
㈠筛选需要处理的属性,将其缓存到一个静态字典中,在需要的时候再取出来。这个初始化的代码如下:
/// 
/// 用户控件类型及自动保存属性成员缓冲字典
/// 
protected static dictionary cachedic = null;
 
/// 
/// 获得成员列表的绑定标识.
/// 
protected static bindingflags flag;
 
/// 
/// 初始化  类.
/// 
static basepage()
{
cachedic = new dictionary();
 
flag = bindingflags.public | bindingflags.nonpublic | bindingflags.instance | bindingflags.getfield | bindingflags.getproperty | bindingflags.flattenhierarchy;
}
 
/// 
/// 当前页面的类型
/// 
protected type currtype = null;
/// 
/// 初始化当前页面的缓冲字典
/// 
protected void initcachedic()
{
// 获得当前实例类型
currtype = page.gettype();
 
memberinfo[] mems = null;
 
if (!cachedic.trygetvalue(currtype, out mems))
{
// 自动保存属性处理
var list = currtype.getmembers(flag)
.where(p => attribute.isdefined(p, typeof(autosave), false))
.toarray();
cachedic[currtype] = list;
}
}
 
可以看到,在调用调用初始化函数 initcachedic 时,系统会做两件事:缓存当前页面类型、筛选需要处理的属性。筛选属性反射操作,执行一次后不再重复。
 
 
㈡在赋值取值时,根据 currtype 找到需要处理的属性,反射调用即可。这里我将属性的赋值操作放在了 oninit 方法中,具体的代码如下:
/// 
/// 引发  事件以对页进行初始化。
/// 
/// 包含事件数据的 
protected override void oninit(eventargs e)
{
if (page.ispostback)
{
// 初始化当前用户控件的缓冲字典
initcachedic();
 
// 获得缓冲数据列表
var list = getcachedata();
 
// 自动加载 autosave 属性保存的值
int index = 0;
foreach (memberinfo info in cachedic[currtype])
{
if (info.membertype == membertypes.property)
{
propertyinfo pi = info as propertyinfo;
object value = list[index];
if (value != null)
pi.setvalue(this, value, null);
}
else if (info.membertype == membertypes.field)
{
fieldinfo fi = info as fieldinfo;
object value = list[index];
fi.setvalue(this, value);
}
index++;
}
}
}
 
其中 getcachedata 方法是获得该页缓存的数据。这些缓存的数据你可以放在 session、database、viewstate、分布式或者其它你能想到的地方。这涉及到了下篇中的内容,这里先卖个关子,相信难不倒聪明的你!
 
㈢在赋值操作时,根据 currtype 找到需要处理的属性,反射赋值即可。这里我将属性的保存操作放在了 saveviewstate 方法中。具体的代码如下:
/// 
/// 在这里实现属性的自动保存。
/// 
protected override object saveviewstate()
{
// 初始化当前用户控件的缓冲字典
initcachedic();
 
// 初始化要保存的属性值列表
arraylist list = new arraylist();
int index = 0;
foreach (memberinfo info in cachedic[currtype])
{
if (info.membertype == membertypes.property)
{
propertyinfo pi = info as propertyinfo;
list[index] = pi.getvalue(this, null);
}
else if (info.membertype == membertypes.field)
{
fieldinfo fi = info as fieldinfo;
list[index] = fi.getvalue(this);
}
}
 
// 保存更改
savecachedata(list);
 
return base.saveviewstate();
}
 
其中 savecachedata 方法是保存该页缓存的数据,和 getcachedata 方法的作用是相反。这里你可以尽情发挥你的想象,比如保存到 session 中?
 
这样吧,为了满足某些人的懒惰心理,我先贴上演示用的数据保存和提取方法。代码如下:
private arraylist getcachedata()
{
return (arraylist)session[currtype];
}
 
private void savecachedata(arraylist data)
{
session[currtype] = data;
}

相关文章

精彩推荐