私の意見では、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" の最初の呼び出しで使用されるオーバーロードで使用されるラムダに渡される引数は "HtmlAttributeManager" です。これは、HtmlTextWriterAttribute と文字列値を取り、インスタンスを返すインデクサーを提供するために HtmlTextWriter をラップする単純なクラスです。その呼び出しは連鎖できます。このクラスには、「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();
}
編集:これの目標の1つは、オーバーヘッドをできるだけ少なくすることであるという点で、おそらくもう少し明確にする必要があります。これが、ラムダの使用を制限した理由です。また、最初はタグを表すクラスを使っていたので、レンダリング前の構文で DOM ツリーのようなものを構築していましたが、構文は非常に似ていました。この解決策は、わずかなメモリ オーバーヘッドが発生するため、断念しました。HtmlAttributeManager クラスの使用にはまだいくつかのこの存在があり、属性の追加にも拡張メソッドを使用することを考えていましたが、インデクサー構文を使用できず、HtmlTextWriter のインターフェイスを肥大化させます。さらに。