HTML 标签如何转换为 HtmlControl?
How are HTML tags converted to HtmlControl?
假设我有这个标记:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<a runat="server" id="myLink" href="<%# Container.DataItem %>">Here</a>
</ItemTemplate>
</asp:Repeater>
在代码隐藏中,我可以发现 <a>
被转换为 HtmlAnchor
:
private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
HtmlAnchor myLink = (HtmlAnchor)Repeater1.FindControl("myLink");
}
但是编译器怎么知道<a>
是HtmlAnchor
呢?它是在编译器中硬编码的吗?
如果我写
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<Foo href="<%# Container.DataItem %>">Here</a>
</ItemTemplate>
</asp:Repeater>
并希望将 <Foo>
标签转换为我的 HtmlFoo
class,我该如何实现?
我只是想对幕后的编译过程有更深入的了解
当您将 runat="server"
添加到 ASP.NET 中的控件时,类型 HtmlControl
的相应变量(或其某些子类)会自动添加到您的页面(在设计器文件中).这样您就可以将该控件作为变量访问。对于最常见的 HTML 控件,有 HtmlControl 的子类(例如 HtmlAnchor
用于 anchor/link 标记)。其他控件(例如 <div>
)获得 HtmlGenericControl
类型。对于那些,您将标记 (div
) 指定为 属性。所以你的 Foo 标签会变成一个 div:一个类型为 HtmlGenericControl
的变量,标签为 "Foo".
编辑: 这是标准的 HTML 元素。如果您创建一个 ASP 控件(例如 <asp:TextBox...>
,那么结果变量将是一个子类或 WebControl 而不是 HtmlControl.
您可以通过深入研究 Reference Source.
来了解 ASP.NET 的很多内部结构
事实证明,从无前缀 HTML 标签到 HtmlControl subclasses 的映射被硬编码在一个名为 HtmlTagNameToTypeMapper:[=16 的内部 class 中=]
static Hashtable _tagMap;
Type ITagNameToTypeMapper.GetControlType(string tagName, IDictionary attributeBag) {
Type controlType;
if (_tagMap == null) {
Hashtable t = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
t.Add("a", typeof(HtmlAnchor));
t.Add("button", typeof(HtmlButton));
t.Add("form", typeof(HtmlForm));
// [and much more...]
_tagMap = t;
}
// [...]
}
GetControlType 由另一个名为 MainTagNameToTypeMapper:
的内部 class 调用
int colonIndex = tagName.IndexOf(':');
if (colonIndex >= 0) {
// [...]
}
else {
// There is no prefix.
// Try the Html mapper if allowed
if (fAllowHtmlTags) {
return _htmlMapper.GetControlType(tagName, attribs);
}
}
没有 public API 来注册更多无前缀的 HTML 控件类型。
在更本地化的范围内,父控件可以自定义其子控件的标签名称的解释方式。为此,派生自 ControlBuilder,覆盖 GetChildControlType, and decorate the parent control class with the [ControlBuilder(typeof(...)] attribute.
假设我有这个标记:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<a runat="server" id="myLink" href="<%# Container.DataItem %>">Here</a>
</ItemTemplate>
</asp:Repeater>
在代码隐藏中,我可以发现 <a>
被转换为 HtmlAnchor
:
private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
HtmlAnchor myLink = (HtmlAnchor)Repeater1.FindControl("myLink");
}
但是编译器怎么知道<a>
是HtmlAnchor
呢?它是在编译器中硬编码的吗?
如果我写
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<Foo href="<%# Container.DataItem %>">Here</a>
</ItemTemplate>
</asp:Repeater>
并希望将 <Foo>
标签转换为我的 HtmlFoo
class,我该如何实现?
我只是想对幕后的编译过程有更深入的了解
当您将 runat="server"
添加到 ASP.NET 中的控件时,类型 HtmlControl
的相应变量(或其某些子类)会自动添加到您的页面(在设计器文件中).这样您就可以将该控件作为变量访问。对于最常见的 HTML 控件,有 HtmlControl 的子类(例如 HtmlAnchor
用于 anchor/link 标记)。其他控件(例如 <div>
)获得 HtmlGenericControl
类型。对于那些,您将标记 (div
) 指定为 属性。所以你的 Foo 标签会变成一个 div:一个类型为 HtmlGenericControl
的变量,标签为 "Foo".
编辑: 这是标准的 HTML 元素。如果您创建一个 ASP 控件(例如 <asp:TextBox...>
,那么结果变量将是一个子类或 WebControl 而不是 HtmlControl.
您可以通过深入研究 Reference Source.
来了解 ASP.NET 的很多内部结构事实证明,从无前缀 HTML 标签到 HtmlControl subclasses 的映射被硬编码在一个名为 HtmlTagNameToTypeMapper:[=16 的内部 class 中=]
static Hashtable _tagMap;
Type ITagNameToTypeMapper.GetControlType(string tagName, IDictionary attributeBag) {
Type controlType;
if (_tagMap == null) {
Hashtable t = new Hashtable(10, StringComparer.OrdinalIgnoreCase);
t.Add("a", typeof(HtmlAnchor));
t.Add("button", typeof(HtmlButton));
t.Add("form", typeof(HtmlForm));
// [and much more...]
_tagMap = t;
}
// [...]
}
GetControlType 由另一个名为 MainTagNameToTypeMapper:
的内部 class 调用int colonIndex = tagName.IndexOf(':');
if (colonIndex >= 0) {
// [...]
}
else {
// There is no prefix.
// Try the Html mapper if allowed
if (fAllowHtmlTags) {
return _htmlMapper.GetControlType(tagName, attribs);
}
}
没有 public API 来注册更多无前缀的 HTML 控件类型。
在更本地化的范围内,父控件可以自定义其子控件的标签名称的解释方式。为此,派生自 ControlBuilder,覆盖 GetChildControlType, and decorate the parent control class with the [ControlBuilder(typeof(...)] attribute.