在我看来,使用HtmlTextWriter渲染HTML并不是非常直观,但如果您在Web表单中实现Web控件,那么您必须使用它.我认为有可能为此创建一个流畅的界面,它更像是它输出的HTML.我想知道人们对我到目前为止提出的语法的看法.
public void Render(HtmlTextWriter writer) { writer .Tag(HtmlTextWriterTag.Div, e => e[HtmlTextWriterAttribute.Id, "id"][HtmlTextWriterAttribute.Name,"name"][HtmlTextWriterAttribute.Class,"class"]) .Tag(HtmlTextWriterTag.Span) .Text("Lorem") .EndTag() .Tag(HtmlTextWriterTag.Span) .Text("ipsum") .EndTag() .EndTag(); }
"Tag","Text"和"EndTag"是HtmlTextWriter类的扩展方法,它返回它所接受的实例,以便可以链接调用.传递给第一次调用"Tag"时使用的重载中使用的lambda的参数是一个"HtmlAttributeManager",它是一个简单的类,它包装一个HtmlTextWriter来提供一个索引器,它接受一个HtmlTextWriterAttribute和一个字符串值并返回实例所以这些电话可以被链接.我也有这个类的方法用于最常见的属性,例如"Name","Class"和"Id",这样你就可以编写上面的第一个调用,如下所示:
.Tag(HtmlTextWriterTag.Div, e => e.Id("id").Name("name").Class("class"))
一个更长的例子:
public void Render(HtmlTextWriter writer) { writer .Tag(HtmlTextWriterTag.Div, a => a.Class("someClass", "someOtherClass")) .Tag(HtmlTextWriterTag.H1).Text("Lorem").EndTag() .Tag(HtmlTextWriterTag.Select, t => t.Id("fooSelect").Name("fooSelect").Class("selectClass")) .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "1"][HtmlTextWriterAttribute.Title, "Selects the number 1."]) .Text("1") .EndTag(HtmlTextWriterTag.Option) .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "2"][HtmlTextWriterAttribute.Title, "Selects the number 2."]) .Text("2") .EndTag(HtmlTextWriterTag.Option) .Tag(HtmlTextWriterTag.Option, t => t[HtmlTextWriterAttribute.Value, "3"][HtmlTextWriterAttribute.Title, "Selects the number 3."]) .Text("3") .EndTag(HtmlTextWriterTag.Option) .EndTag(HtmlTextWriterTag.Select) .EndTag(HtmlTextWriterTag.Div); }
希望你能够"破译"这个片段输出的HTML,至少这个想法.
请给我任何关于如何改进语法的想法,可能是更好的方法名称,也许是其他一些方法.
编辑:我认为,如果不使用流畅的界面,看看相同的代码片段会是什么样子可能会很有趣,以便进行比较:
public void RenderUsingHtmlTextWriterStandardMethods(HtmlTextWriter writer) { writer.AddAttribute(HtmlTextWriterAttribute.Class, "someClass someOtherClass"); writer.RenderBeginTag(HtmlTextWriterTag.Div); writer.RenderBeginTag(HtmlTextWriterTag.H1); writer.Write("Lorem"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Id, "fooSelect"); writer.AddAttribute(HtmlTextWriterAttribute.Name, "fooSelect"); writer.AddAttribute(HtmlTextWriterAttribute.Class, "selectClass"); writer.RenderBeginTag(HtmlTextWriterTag.Select); writer.AddAttribute(HtmlTextWriterAttribute.Value, "1"); writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 1."); writer.RenderBeginTag(HtmlTextWriterTag.Option); writer.Write("1"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Value, "2"); writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 2."); writer.RenderBeginTag(HtmlTextWriterTag.Option); writer.Write("2"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Value, "3"); writer.AddAttribute(HtmlTextWriterAttribute.Title, "Selects the number 3."); writer.RenderBeginTag(HtmlTextWriterTag.Option); writer.Write("3"); writer.RenderEndTag(); writer.RenderEndTag(); writer.RenderEndTag(); }
编辑:我应该更明确一点,因为其中一个目标是它应该产生尽可能少的开销,这就是为什么我限制了lambdas的使用.另外,我首先使用了一个表示标记的类,以便在渲染之前通过语法构建类似于DOM树的东西,但语法非常相似.我放弃了这个解决方案,因为它会产生轻微的内存开销.在使用HtmlAttributeManager类时仍然存在一些这样的问题,我一直在考虑使用扩展方法来追加属性,但是我不能使用索引器语法,它也会膨胀HtmlTextWriter的接口更.