第一篇:初识ASP.NET控件开发_第三节:“生死有序”的控件生命周期

简介:

一、Page本质是一个Control

我们首先要澄清的第一个概念是页面类Page本质是一个控件类,它派生于TemplateControl类,而TemplateControl派生自Control类。既然饭我没有乱吃,自然话也不会乱讲。借田有良老师的翠花给大家上证据如下:

clipboard clipboard[1]

二、Control的“生死之序”

clipboard[2] 

  • 1.实例化(Instantiate) 
    我们写控件一般不要接触此活动。
  • 2.初始化(Initialize) 
    【初始化自己,创建它的子控件(但该过程控件的状态没有加载)。触发该控件的OnInit()事件。】我们写控件一般不要接触此活动。 
    【跟踪视图状态(Tracking View State)*  】这个比较重要,涉及到视图状态,一般情况下不必重载此方法。
  • 3.加载视图状态(Load view state) * 
    只会在回传过程中调用此方法,用法同上。
  • 4.加载回发数据(Load postback data)
    如果你的控件生成之后要和客户端交互,那么这个方法就很重要,只会在回传过程中调用此方法。
  • 5.加载(Load) 
    这个活动一般只是Page的OnLoad才会要去管它,我们写控件一般不要接触此方法。
  • 6.更改通知(Raise changed events)
    控件生成后,数据被客户端更改过,和加载回传数据是一路的。
  • 7.处理回发事件(Raise postback event)* 
    一般用于实现IPostBackEventHandler接口的控件的把客户端事件转化成服务器端事件。只用于回传过程。
  • 8.预呈现(PerRender)**
    生成前期工作,这个是很重要的一个过程,通过重载OnPreRender方法实现自定义。
  • 9.保存视图状态(Save view state)* 
    如果所以信息都是用ViewState[xxx]这种方式来保存,不必重载,只有自定义视图状态管理时才重载此方法,当然,这里做了手脚,LoadViewState也就一定要和这里的Save方法配套。
  • 10.呈现(Render)*** 
    这个是主角,控件成生什么东东基本就由这里管了。
  • 11.卸载(Unload)
  • 12.释放(Dispose)

三、控件树的“合成模式(Composite)”

从设计模式的角度讲,页面模型是一个“合成模式(Composite)”,它本身是一棵由多层控件组成的结构树,顶层是Page,以下有叶有树枝,叶是不再包涵子控件的控件,枝是又包涵子控件的控件,每一层控件的"初始化\加载视图状态\加载\预呈现\保存视图状态\卸载"等方法都会调用子控件的对应方法,父控件调用子控件的方法,子又调用孙的,如此递归。

1、初始化:

internal virtual void InitRecursive(Control namingContainer)
{
    this.ResolveAdapter();
    if (this._controls != null)
    {
        if (this.flags[128])
        {
            namingContainer = this;
        }
        string collectionReadOnly = this._controls.SetCollectionReadOnly("Parent_collections_readonly");
        int count = this._controls.Count;
        for (int i = 0; i < count; i++)
        {
            Control control = this._controls[i];
            control.UpdateNamingContainer(namingContainer);
            if (control._id == null && namingContainer != null && !control.flags[64])
            {
                control.GenerateAutomaticID();
            }
            control._page = this.Page;
            control.InitRecursive(namingContainer);
        }
        this._controls.SetCollectionReadOnly(collectionReadOnly);
    }
    if (this._controlState < ControlState.Initialized)
    {
        this._controlState = ControlState.ChildrenInitialized;
        if (this.Page != null && !this.DesignMode && this.Page.ContainsTheme && this.EnableTheming)
        {
            this.ApplySkin(this.Page);
        }
        if (this.AdapterInternal != null)
        {
            this.AdapterInternal.OnInit(EventArgs.Empty);
        }
        else
        {
            this.OnInit(EventArgs.Empty);
        }
        this._controlState = ControlState.Initialized;
    }
    this.TrackViewState();
}

2、加载视图状态:

internal void LoadViewStateRecursive(object savedState)
{
    if (savedState == null || this.flags[4])
    {
        return;
    }
    if (this.Page != null && this.Page.IsPostBack)
    {
        object obj = null;
        Pair pair = savedState as Pair;
        object first;
        ArrayList arrayList;
        if (pair != null)
        {
            first = pair.First;
            arrayList = (ArrayList)pair.Second;
        }
        else
        {
            Triplet triplet = (Triplet)savedState;
            first = triplet.First;
            obj = triplet.Second;
            arrayList = (ArrayList)triplet.Third;
        }
        try
        {
            if (obj != null && this.AdapterInternal != null)
            {
                this.AdapterInternal.LoadAdapterViewState(obj);
            }
            if (first != null)
            {
                this.LoadViewState(first);
            }
            if (arrayList != null)
            {
                if (this.LoadViewStateByID)
                {
                    this.LoadChildViewStateByID(arrayList);
                }
                else
                {
                    this.LoadChildViewStateByIndex(arrayList);
                }
            }
        }
        catch (InvalidCastException)
        {
            throw new HttpException(SR.GetString("Controls_Cant_Change_Between_Posts"));
        }
        catch (IndexOutOfRangeException)
        {
            throw new HttpException(SR.GetString("Controls_Cant_Change_Between_Posts"));
        }
    }
    this._controlState = ControlState.ViewStateLoaded;
}
internal void LoadChildViewStateByID(ArrayList childState)
{
    int count = childState.Count;
    for (int i = 0; i < count; i += 2)
    {
        string text = (string)childState[i];
        object obj = childState[i + 1];
        Control control = this.FindControl(text);
        if (control != null)
        {
            control.LoadViewStateRecursive(obj);
        }
        else
        {
            this.EnsureOccasionalFields();
            if (this._occasionalFields.ControlsViewState == null)
            {
                this._occasionalFields.ControlsViewState = new Hashtable();
            }
            this._occasionalFields.ControlsViewState[text] = obj;
        }
    }
}

3、加载:

internal virtual void LoadRecursive()
{
    if (this._controlState < ControlState.Loaded)
    {
        if (this.AdapterInternal != null)
        {
            this.AdapterInternal.OnLoad(EventArgs.Empty);
        }
        else
        {
            this.OnLoad(EventArgs.Empty);
        }
    }
    if (this._controls != null)
    {
        string collectionReadOnly = this._controls.SetCollectionReadOnly("Parent_collections_readonly");
        int count = this._controls.Count;
        for (int i = 0; i < count; i++)
        {
            this._controls[i].LoadRecursive();
        }
        this._controls.SetCollectionReadOnly(collectionReadOnly);
    }
    if (this._controlState < ControlState.Loaded)
    {
        this._controlState = ControlState.Loaded;
    }
}

4、预呈现:

internal virtual void PreRenderRecursiveInternal()
{
    if (!this.Visible)
    {
        this.flags.Set(16);
    }
    else
    {
        this.flags.Clear(16);
        this.EnsureChildControls();
        if (this.AdapterInternal != null)
        {
            this.AdapterInternal.OnPreRender(EventArgs.Empty);
        }
        else
        {
            this.OnPreRender(EventArgs.Empty);
        }
        if (this._controls != null)
        {
            string collectionReadOnly = this._controls.SetCollectionReadOnly("Parent_collections_readonly");
            int count = this._controls.Count;
            for (int i = 0; i < count; i++)
            {
                this._controls[i].PreRenderRecursiveInternal();
            }
            this._controls.SetCollectionReadOnly(collectionReadOnly);
        }
    }
    this._controlState = ControlState.PreRendered;
}

5、保存视图状态:

internal object SaveViewStateRecursive(ViewStateMode inheritedMode)
{
    if (this.flags[4])
    {
        return null;
    }
    bool flag;
    if (this.flags[8388608])
    {
        if (this.flags[16777216])
        {
            flag = true;
            inheritedMode = ViewStateMode.Enabled;
        }
        else
        {
            flag = false;
            inheritedMode = ViewStateMode.Disabled;
        }
    }
    else
    {
        flag = (inheritedMode == ViewStateMode.Enabled);
    }
    object obj = null;
    object obj2 = null;
    if (flag)
    {
        if (this.AdapterInternal != null)
        {
            obj = this.AdapterInternal.SaveAdapterViewState();
        }
        obj2 = this.SaveViewState();
    }
    ArrayList arrayList = null;
    if (this.HasControls())
    {
        ControlCollection controls = this._controls;
        int count = controls.Count;
        bool loadViewStateByID = this.LoadViewStateByID;
        for (int i = 0; i < count; i++)
        {
            Control control = controls[i];
            object obj3 = control.SaveViewStateRecursive(inheritedMode);
            if (obj3 != null)
            {
                if (arrayList == null)
                {
                    arrayList = new ArrayList(count);
                }
                if (loadViewStateByID)
                {
                    control.EnsureID();
                    arrayList.Add(control.ID);
                }
                else
                {
                    arrayList.Add(i);
                }
                arrayList.Add(obj3);
            }
        }
    }
    if (this.AdapterInternal != null)
    {
        if (obj2 != null || obj != null || arrayList != null)
        {
            return new Triplet(obj2, obj, arrayList);
        }
    }
    else
    {
        if (obj2 != null || arrayList != null)
        {
            return new Pair(obj2, arrayList);
        }
    }
    return null;
}

6、卸载:

internal virtual void UnloadRecursive(bool dispose)
{
    Page page = this.Page;
    if (page != null && page.RequiresControlState(this))
    {
        page.UnregisterRequiresControlState(this);
        this.RareFieldsEnsured.RequiredControlState = true;
    }
    if (this.flags[2097152])
    {
        this._id = null;
        this.flags.Clear(2097152);
    }
    if (this._controls != null)
    {
        string collectionReadOnly = this._controls.SetCollectionReadOnly("Parent_collections_readonly");
        int count = this._controls.Count;
        for (int i = 0; i < count; i++)
        {
            this._controls[i].UnloadRecursive(dispose);
        }
        this._controls.SetCollectionReadOnly(collectionReadOnly);
    }
    if (this.AdapterInternal != null)
    {
        this.AdapterInternal.OnUnload(EventArgs.Empty);
    }
    else
    {
        this.OnUnload(EventArgs.Empty);
    }
    if (dispose)
    {
        this.Dispose();
    }
    if (this.IsReloadable)
    {
        this._controlState = ControlState.Constructed;
    }
}

四、InitRecursive、LoadRecursive、PreRenderRecursiveInternal、UnloadRecursive函数看事件的触发顺序

clipboard[14]

作者: 韩兆新
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
分类:  [06]ASP.NET相关

本文转自韩兆新博客博客园博客,原文链接:http://www.cnblogs.com/hanzhaoxin/p/4046951.html,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
2月前
|
开发框架 JavaScript 前端开发
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
|
4月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
4天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
30天前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
9 0
|
30天前
深入.net平台的分层开发
深入.net平台的分层开发
47 0
|
2月前
|
开发框架 前端开发 .NET
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
为了便于大家查找,特将之前开发的.Net Core相关的五大案例整理成文,共计440页,32w字,免费提供给大家,文章底部有PDF下载链接。
32 1
福利来袭,.NET Core开发5大案例,30w字PDF文档大放送!!!
|
2月前
|
SQL 开发框架 前端开发
ASP.NET WEB项目中GridView与Repeater数据绑定控件的用法
ASP.NET WEB项目中GridView与Repeater数据绑定控件的用法
32 0
|
3月前
|
SQL 开发框架 JavaScript
分享33个ASP.NET电子商务源码和40个ASP.NET控件组件源码,总有一款适合您
分享33个ASP.NET电子商务源码和40个ASP.NET控件组件源码,总有一款适合您
29 0
|
3月前
|
C#
.NET开发中合理使用对象映射库,简化和提高工作效率
.NET开发中合理使用对象映射库,简化和提高工作效率