ASP.NET 1.1 可扩展主页框架:模式导向设计






4.90/5 (88投票s)
2004年7月1日
9分钟阅读

362962

6500
使用 ASP.NET 和 C# 开发主页框架。
引言
本文旨在详细阐述框架开发过程中涉及的流程,并以一个使用 ASP.NET 和 C# 开发的“主页框架”为例。本文将向您解释使用 UML 的面向对象设计方法、框架中涉及的设计模式,以及一些模式导向架构与设计 (POAD) 的知识,可谓包罗万象。
主页框架开发
在面向对象软件工程中,一切都始于用例。在开发 Web 应用程序时,其中一个用例是“用户需要一个始终如一的外观和感觉”。
这有什么大不了的?我们每天到处都能看到一致的网站,等等等等……我们看到漂亮的“性感”网站,但我们没有看到一件事(好吧!你看不见),如果整个网站需要一个更改,维护成本会是多少。现在看起来很麻烦了 :)
除了用于一致性的一些 CSS 样式表,我们还需要什么?一个框架,一个主页框架,它应该可扩展、易于使用、可插拔且可进行视觉修改!(听起来很棒!多么美好的愿望 :D)ASP.NET 中目前不存在这样的东西(Whidbey 中有一个,但还有很长的路要走)。
我开始在网上搜索,找到了一些有趣的文章
这些文章是非常好的起点,所以我从它们中汲取了所有宝贵的建议并进一步深入,因为我正在寻找一种可重用/可扩展的框架。我承担了重新设计从未存在过的整个轮子的责任,这怎么样 ;)。
我所采取的方法,我所设计的是模式导向架构和设计 (POAD),而不是设计模式,它们是不同的。我称之为 POAD,因为我的应用程序具有一种独特的“外观和感觉”,它遵循一种模式。POAD 意味着您拥有整个原型模式,您的应用程序将遵循该模式,但稍后会被具体结构所覆盖(这个概念需要一整篇文章,我稍后会写,并附带一些示例,希望在下个月)。所以主页有页眉、页脚、导航器、菜单/子菜单和内容占位符,这些占位符将根据具体页面的需要稍后填充,怎么样,听起来不错。让我们进一步!以下是设计基于 POAD 的软件所涉及的步骤。
- 绘制您的框架将提供的整个抽象模式。
- 找出负责完成工作的对象。
- 找出它们之间的关系。
- 找出所需的设计模式。
- 在设计对象时,详细阐述它们,并找出它们的功能。
- 编写测试用例。
涉及的步骤
绘制您的框架将提供的整个抽象模式。
这是我们框架的原型模式
图 1(主页布局/模式)
主 Web 用户控件
如果我们把这个模式分解成对象,很明显我们应该有一些骨架或模板作为占位符,也就是说,应该有一个主页,它由占位符组成,比如页眉、页脚、徽标、菜单、导航器和内容等等。
由于我们的计划是可视化地改变这些占位符,我们可以安全地将这些占位符放入一个用户控件(`PageUserControlBase`)中,该控件又包含所有占位符。称之为 Master 用户控件,您可以在其中定义这些内容的布局。现在,我们的模型将有一个 Master Page,它又由 Master User-Control(`PageUserControlBase`)组成,而 Master User-Control 又由占位符组成,就像这样
越来越近了,太棒了!:) 现在决定通过用户控件等提供可视化部分。我们希望这个用户控件在运行时可插拔,所以我们将使用 web.config 在运行时动态加载它,像这样
<appSettings>
<add key="MasterPageUserControl" value="MasterPageUserControl.ascx"/>
</appSettings>
我们的框架将 Master User-Control (`PageUserControlBase`) 类的所有功能封装在一个程序集中,作为基类/抽象类,以便我们将来需要时可以对其进行扩展。它看起来是这样的
通过这种方法,如果将来我们决定采用其他外观和感觉的母版用户控件,我们所需要做的就是扩展 `PageUserControlBase` 类并使用它
<%@ Control Inherits="Shams.Web.UI.MasterPages.PageUserControl" %>
或者这样使用它
<%@ Control Inherits="Shams.Web.UI.MasterPages.PageUserControlExtra" %>
`PageUserControl` 或 `PageUserControlExtra` 将为我们提供对 `WebControls.PlaceHolder`(s) 的访问。以下是 `PageUserControlBase.ascx` 的样子:
这很简单,对吧?是的,它就是这样。现在可视化组件可以很容易地扩展,并且可以通过 `web.config` 进行插拔,并且已经准备好了。所以在设计框架时,我们目标明确,这是一个可扩展和可插拔的框架,太棒了 :)。还需要什么呢?嗯,还有很多工作要做。到目前为止,我们所做的一切都是通过可插拔的 Master User Control-Base 提供了一致的外观和感觉。我们还有很长的路要走。让我们首先分析一下 HTML/aspx 页面是什么样子的
你可以看到页面本身有四个部分,让我们仔细检查它们
- A 部分:- HTML 头部,描述代码隐藏语言、页面标题、元信息和 HTML 正文等。
- B 部分:- 表单区域。
- C 部分:- 主用户控件区域,[或任何控件]。
- D 部分:- HTML 页脚区域。
主自定义控件
每个页面只能有一个 HTML 表单。我们将所有服务器控件放在此表单中(C 部分)。因此,我们需要另一个对象来封装上述所有 HTML 渲染内容,例如 A 部分、B 部分、C 部分和 D 部分。如果您查看 `Control` 类,它具有我们正在寻找的所有功能。`Control` 是一个复合控件,这意味着我们可以在其中放置其他控件。因此,通过扩展 `Control` 对象来开始使用自定义控件是一个很好的起点。这个扩展的自定义控件,我们称之为 `PageControlBase`,将提供 HTML 渲染功能,并且它将包含一个 `System.Web.UI.HtmlControls.HtmlForm` 对象。这个 Form 对象将用于添加我们著名的主用户控件或 C 部分。现在,我们的主页面将由一些主自定义控件和主用户控件组成。这是展示所有这些的 UML 图
现在我们有了一个可插拔的主用户控件,还需要一个自定义控件来创建所有 HTML 部分。
我们需要一个集成器类,它将主用户控件插入自定义控件表单并将其附加到主页。这就是派生自 `UI.Page` 类的 `MasterPageBase` 类:-
主页框架中使用的设计模式
当您计划任何基于原型或遵循 POAD 的框架时,最有效的模式是模板设计模式。以下是演示此模式的代码
public interface IPageControl
{
System.Web.UI.Control ParentControl();
void HtmlRenderStarts();
void PreHtmlRender();
void HtmlRender();
void PostHtmlRender();
void HtmlRenderEnds();
/// <summary>
/// The title page can be set with this property
/// </summary>
string PageTitle
{
get;
set;
}
/// <summary>
/// </summary>
string MetaInfo
{
get;
set;
}
}
我们定义了执行序列/模式,该模式稍后将被派生类覆盖。
模板设计模式在两种情况下使用
- 在自定义控件中定义的模板:-
- 这是使用相同设计模式的另一个地方
使用的其他模式是工厂模式和复合设计模式。工厂模式用于创建类,并且应该提供一个位置;如果计划在它们的创建周围放置一些业务逻辑,我们可以在不破坏现有代码的情况下完成它。
复合模式内置于 .NET 框架中,例如 `Control` 类本身就是基于复合模式的。复合模式的简单形式是一个对象列表的列表。我没有重新发明自己的对象容器,而是将 `Control` 类作为我的起点。
就这样,我们完成了框架。你所需要做的就是让你的页面继承自 `MasterPage` 类,并重写你希望在具体类中改变的内容。我们如何做到这一点,在下面的 UML 图中显示了
让我们讨论一下在实现过程中会遇到的一些典型场景
1. 创建主页骨架:-
如前所述,我们只需要从 `MasterPageBase` 派生。以下是代码片段作为示例
这是我们将得到的结果;这是一个主页骨架。
视觉设置来自 `web.config`,即
<appSettings>
<add key="MasterPageUserControl" value="MasterPageUserControl.ascx"/>
</appSettings>
如果你的 `MasterPage` 有其他布局,你可以创建自己的用户控件并修改 `web.config` 中的签名。
以下是上述场景不太详细的对象序列图:-
2. 从主页骨架创建主页:-
我们将从 `MasterPageBase` 创建一个 `MasterPage` 类,并用我们自己的 `UserControl`s 覆盖占位符。以下是此示例代码片段:-
这是我为我的示例网站创建的主页面
3. 从您刚刚创建的主页创建自己的页面。
您所需要做的就是将这个 `MasterPage` 类作为所有页面的基类,并覆盖您可能想要不同的功能,并使内容保持一致:-
以下是网站其余页面的建议 UML 图:-
4. 如果您有多个主页(MDI 场景)
在此特定场景中,您将重写 `LoadPageUserControl()` 函数,其中框架会动态加载用户指定的主控件。以下是此场景的代码片段:-
这是表示此场景的 UML 图:-
以下是通用情况的 UML 表示,MDI(多文档界面)或 Web 应用程序中的多主界面(MMI):-
好了,暂时就这些了,希望您和我一起享受了这次 MMI 之旅,虽然旅途有点颠簸,但我们很高兴安全地回到了家(页面)。现在享受这个框架吧,您只需包含程序集 `Shams.Web.UI.MasterPages.dll` 即可开始使用它。我还提供了一个示例,可以帮助您设计应用程序。请将您的反馈发送给我,以便进一步改进框架,谢谢。
结论
软件架构围绕结构展开,框架为其提供了结构。框架是任何正在开发的应用程序的基础。糟糕的基础会导致糟糕的应用程序,需要更多的维护成本,并且本质上效率低下。因此,无论何时决定开发框架,都要寻找在该特定业务领域具有丰富设计经验的领域专家,这样,您将能够开发出可重用且可扩展的软件。
祝你好运!
干杯。
电子邮件: shams_mukhtar@yahoo.com。