Pregunta

Estoy escribiendo el método RenderContents() de mi control de servidor ASP.NET. El método utiliza un objeto HtmlTextWriter para representar el contenido de salida. Para el control que estoy escribiendo, usar los métodos de StringBuilder parece que requerirá muchas líneas de código para abrir y cerrar cada etiqueta y agregar cada atributo a la secuencia. Al final siento que voy a terminar con un código que es mucho más largo de lo necesario.

Estaba pensando que si usaba una clase encadenable como <=>, mi código sería mucho más limpio de leer y más fácil de escribir.

Lo que me preguntaba era, ¿hay alguna razón para usar el objeto <=> para representar todo el contenido de mi control? Además de las comprobaciones de seguridad (supongo), incluye asegurarse de que no escribe etiquetas en el orden incorrecto o crea un marcado no válido, no veo una razón.

Parece que sería más fácil hacer algo como esto:

protected override void RenderContents(HtmlTextWriter output)
{
    StringBuilder s = new StringBuilder();
    s.Append("lots")
     .Append("of")
     .Append("strings");

    output.BeginRender();
    output.Write(s.ToString());
    output.EndRender();
}

¿Hay alguna razón por la cual sería una mala idea?

Actualizar
En respuesta a la respuesta de Mehrdad Afshari :
 No pensé mucho en los requisitos de memoria de tener un objeto <=> separado instanciado. ¿Qué hay de hacer un contenedor para HtmlTextWriter para que se pueda encadenar y no se cree una cadena adicional?

public class ChainedHtmlTextWriter
{
    private HtmlTextWriter _W;
    public ChainedHtmlTextWriter(HtmlTextWriter writer)
    {
        _W = writer;
    }

    public ChainedHtmlTextWriter Write<T>(T value) 
    { 
        _W.Write(value); 
        return this; 
    }

    public ChainedHtmlTextWriter WriteLine<T>(T value)
    {
        _W.WriteLine(value);
        return this;
    }
}
¿Fue útil?

Solución

Trabajo en una aplicación donde los desarrolladores siguieron el horrible camino que estás explorando. Esto se remonta a los días en que tenía que escribir sus propios archivos ISAPI que escupían código html. Es un dolor de cabeza constante trabajar. Si su código es principalmente cadenas, entonces algo está mal.

La mayor parte del código de este tipo que cambio modifico los objetos del servidor, configuro sus propiedades como lo desee y luego les digo .RenderControl (escritor). Esto hace que el código sea mucho más fácil de leer y trabajar. Si hay un impacto en el rendimiento de los gastos generales que esto conlleva, estoy dispuesto a aceptarlo (de hecho, la aplicación generalmente se ejecuta más rápido después de haber realizado mis cambios, por lo que anecdóticamente este no es el caso, pero no he perfilado mi código).

Un inconveniente simple para codificar sus cosas en cadenas es cuando cambian los estándares HTML. El código en el que trabajo fue escrito en 04/05, y desde entonces & Lt; BR & Gt; se ha convertido en < br / > y las etiquetas html en mayúsculas ya no son kosher, etc. Si habían estado usando controles de servidor, esos controles de servidor han cambiado su html de salida sin que tengamos que hacer nada. Este es solo un ejemplo simple.

EDITAR: Ah, y por cierto, BeginRender y EndRender no tienen ninguna implementación. Son marcadores de posición para que pueda anular y proporcionar una funcionalidad personalizada en una clase derivada de HtmlTextWriter.

EDIT2: a veces es un poco oneroso siempre usar controles de servidor, como para contenedores y otras cosas. Estaría haciendo muchos .Controls.Add () y luego renderizaría el contenedor más tarde. Entonces a veces hago esto:

writer.AddAttribute(HtmlTextWriterAttribute.Class, "myContainerClass");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
// do some stuff, .RenderControl on some other controls, etc.
writer.RenderEndTag();

Como se mencionó, esto hará que html sea correcto incluso si el html de un div cambia en el futuro, porque no tengo cadenas codificadas.

Otros consejos

En cuanto al rendimiento, esto requerirá que se realicen más copias de cadena. HtmlTextWriter escribe directamente en el búfer de salida. StringBuilder por otro lado, tiene su propio buffer. Cuando llama a ToString en output.Write, se debe construir una nueva cadena y luego se escribirá en el búfer de salida por <=>. Requiere mucho más trabajo por hacer.

No creo que deba llamar a BeginRender / EndRender, eso es lo que hace la página.

No puedo ver cómo usar el generador de cadenas ahorrará trabajo al usar los métodos propios de HtmlTextWriters.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top