...
    View Article        

Current Articles | Categories | Search | Syndication

Page: 2 of 3
Previous Page | Next Page
posted @ Monday, May 12, 2008 10:07 PM by SkySigal

 

If Deferred Property Setting works so well, why don't we see it more often?

That's a fair question.

Exposure:

First of all, that's not exactly true... It's all around us -- just not visibly.

What is happening is that there are two important books on how to write ASP.NET Controls (Nikhils and [TODO:Lookup]) and they both demonstrate the Direct Property Setting approach. And why not: their server control examples were so simple, and did not address real-world complications such as Layout variables, that they did not warrant a demonstration of Deferred Property Setting.  So there is a lot of visibility for the Direct Property Setting approach.

But the MS Team that put together the Controls that are part of the framework did use Deferred Property Setting in most cases, rather than Direct Property Setting, so that should tell you something...
Unfortunately, since it takes Reflector to see this code, this approach simply just gets a lot less publicity.

Requires Homework:

Maybe the other reason that Deferred Property Setting gets less exposure is that it takes more lines of code, and at least a decent understanding the effects IStateManager.TrackViewState() has on what is sent to the client.

 

"But I saw in Reflector that the MS Team sometimes do use EnsureChildControls()...".
Yeah. And Nay. I saw that too.  And for a second it stumped me.
But if you look at FormView, notice how it is used:

    [
    Browsable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
    ]
    public virtual FormViewRow HeaderRow{
          get{
                if (this._headerRow == null){
                      this.EnsureChildControls();
                }
                return this._headerRow;
          }
    }

 

First of all, because all the other properties in the control are done with Deffered Property Setting, even if this calls EnsureChildControls() 100 times in a row, none of the other property values will be lost when if ChildControlsCreated is reset and  EnsureChildControls() is called more than once.

Secondly, let's look at it a little closer: it's not only Readonly, but Browsable(false). In other words, it won't be set by declarative tag Attributes, nor by a web programmer via code -- so unlike the Direct Property Setting problem, we can control the order in which these variables are referred to (ie putting them last).

 

What about other controls in the Framework?

We took a good scan of other controls, and basically saw several patterns as being relevant to the MS team:

For one, these may be of help to some people,

  • TemplateContainer properties always invoke EnsureChildControls() first.
  • ITemplate properties always reset the ChildControlsCreated flag.
  • Layout properties (eg: Orientation, ControlType, etc.) always reset the ChildControlsCreated flag.

But its really these patterns we are looking for today:

  • All public properties wrap private fields.
  • Private Fields values are transferred either in CreateChildControls() or in PrepareControlHierarchy() depending on the type of property.
    • In CreateChildControls() if:
      • ListItems.
      • ControlType, etc.
      •  
    • In PrepareControlHierarchy() (post-SaveViewState())) if:
      • Text for labels, buttons, etc. (no need for them earlier).
      • Images URLs  (image URLs are not needed ClientSide).
      • Styles are applied post-SaveViewState.
        • Note:
          This is specifically the part that is hard to swallow: it takes time to copy attributes from one Style object to another, so this transferring values really feels...heavy handed, especially when you consider that to copy a style from location to another takes the same amount of time, regardless as to whether its just to transfer the ClassName property value, or all of the Style's properties

          But replacing the child control's Style object would get rid of the ability to apply Control-wide Styles such as font:
          • Copy Child's Style-Font to Child:
          • Copy Containers Style-Font to Child:...wrong. So is Merge.
          • So although I don't like it in terms of speed, it is the only way I can see these controls remaining capable of inheriting styles from containers, and remaining true to object oriented interface design patterns.
          • This heavy handed copying doesn't get any easier to absorb the deeper the controls are nested: if we are talking about a CompositeControl that nests a CompositeControl that nests a Button, and we want to expose a ButtonStyle at the top, it's going to be copied to the inner Composite, which is going to copy it to the button...ie 2 copies.
          • Obviously, direct wiring sometimes looks a lot faster...but that's just the way it is. The only thing I can think of in terms of making this bottleneck faster is to change the design pattern used to work with Styles so that it can MergeWith only if the Style has been created -- if not, skip and save time:
            //Test to see if Style exists first
            //then apply:
            //NB: Work with the private field rather than the public property
            //whose get; statement will create a new Style object:
            if (this._ButtonStyle!=null){
                this.Button.Style.MergeWith(this._ButtonStyle);
            }
powered by metaPost
Page: 2 of 3
Previous Page | Next Page

Comments

By Michel @ Tuesday, October 06, 2009 11:56 PM
Thanks! Good article about persisting properties. This helped me a lot solving some issues with my server control!

Click here to post a comment

             
Copyright 2007 by Sky Sigal