Viewstate Plumbing: add the pipes after the walls are built
I hate plumbing. Repetitive code that you write on every web page. Viewstate is about the best thing ASP.NET ever invented, but they didn't spread its goodness through their framework. If I want a page variable in viewstate, I have to remember to put it there and pull it out, either via the ViewState[] collection or by actually overriding methods. Silly.
My ideal would be to simply mark a variable with an attribute -- "hey, I want this in my viewstate". Like so
[ViewState]
protected int _myStatus;
But the ASP.NET framework's Page class wouldn't know what to do with this. Sadly, we can't change or extend methods of that class during run-time like we might in more dynamic languages, e.g. Ruby. But if we're willing to use a new base class, the plumbing is pretty easy to take care of. On load and save viewstate events, we simply scan our variables for those attributed appropriately. Then when I want a variable in ViewState, I just say so. The pipes get built for me and stay behind the walls, rather than intruding all over my Load and PreRender functions.
[AttributeUsage(AttributeTargets.Field)]
public class ViewStateAttribute : Attribute {}
/* inside your favorite Page subclass */
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
ForEachViewstateField(delegate(FieldInfo fi) { fi.SetValue(this, ViewState[fi.Name]); });
}
private void ForEachViewstateField(Action a)
{
foreach (FieldInfo fi in GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
object[] atts = fi.GetCustomAttributes(typeof (ViewStateAttribute), true);
if (atts.Length > 0) a(fi);
}
}
protected override object SaveViewState()
{
ForEachViewstateField(delegate(FieldInfo fi) { ViewState[fi.Name] = fi.GetValue(this); });
return base.SaveViewState();
}
Labels: programming

0 Comments:
Post a Comment
Links to this post:
Create a Link
<< Home