C # - объектно-ориентированный способ написания HTML в виде строки? - PullRequest
3 голосов
/ 05 января 2010

Я пытаюсь программно отправить по электронной почте все файлы dll и их версии в каталоге, рекурсивно. Я хотел бы отправить электронное письмо как вывод HTML, используя таблицу. Есть ли хороший объектно-ориентированный способ сделать это? Я бы не хотел писать все теги от руки.

Что-то вроде:

private string getHTMLString()
{
    DirectoryInfo di = new DirectoryInfo("some directory");
    FileInfo[] files = di.GetFiles("*.dll", SearchOption.AllDirectories);
    foreach (FileInfo file in files)
    {
        Assembly assembly = Assembly.LoadFile(file.FullName);
        string version = assembly.GetName().Version.ToString();
    }
 }

Ответы [ 8 ]

8 голосов
/ 05 января 2010

Вы можете сделать это OO, создав экземпляр System.Web.UI.WebControls.Table, добавив TableRows и TableCells, а затем вызвав Table.RenderControl в HtmlTextWriter, но, честно говоря, это будет отстой:)

        var tbl = new System.Web.UI.WebControls.Table();

        DirectoryInfo di = new DirectoryInfo("some directory");
        FileInfo[] files = di.GetFiles("*.dll", SearchOption.AllDirectories);
        foreach (FileInfo file in files)
        {
            Assembly assembly = Assembly.LoadFile(file.FullName);
            string version = assembly.GetName().Version.ToString();

            var tr = new System.Web.UI.WebControls.TableRow();
            var tc = new System.Web.UI.WebControls.TableCell();
            tc.Text = HttpUtility.HtmlEncode(version);
            tr.Cells.Add(tc);
            tbl.Rows.Add(tr);
        }

        using (var ts = new StringWriter())
        using (var html = new System.Web.UI.HtmlTextWriter(ts))
        {
            // Not entirely sure about this part
            tbl.RenderControl(html);
            html.Flush();
            string htmlString = ts.ToString();
        }
7 голосов
/ 05 января 2010

Это может быть излишним, но вы можете использовать LINQ to XML для генерации вашей HTML-строки ... Вот ваш код, используя LINQ и XElement для генерации простой таблицы.

Единственное, с чем вам нужно быть осторожным, это пустые теги, которые недопустимы в качестве самозакрывающихся тегов в HTML. Например, пустой TD: new XElement("td") будет отображаться как <td/>, что не является допустимым HTML. Вы можете исправить это, вставив пустую строку в качестве содержимого: new XElement("td", String.Empty) - это выведет <td></td>.

private string GetHtmlString()
{
    DirectoryInfo di = new DirectoryInfo("some directory");
    FileInfo[] files = di.GetFiles("*.dll", SearchOption.AllDirectories);

    var container = new XElement("table",
        from file in files
        let assembly = Assembly.LoadFile(file.FullName)
        select new XElement("tr", 
            new XElement("td", file.FullName),
            new XElement("td", assembly.GetName().Version.ToString())
        )
    );

    return container.ToString();
 }
7 голосов
/ 05 января 2010

На самом деле вы можете использовать HtmlTextWriter и использовать перечисление HtmlTextWriterTag для создания тегов, без необходимости писать вручную «<» и «>».

Пример:

StringBuilder sb = new StringBuilder();

using (HtmlTextWriter w = new HtmlTextWriter(new StringWriter(sb)))
{
      w.RenderBeginTag(HtmlTextWriterTag.P);

      w.AddStyleAttribute(HtmlTextWriterStyle.Color, "red");

      w.RenderBeginTag(HtmlTextWriterTag.Span);

      w.Write("This is some text");

      w.RenderEndTag();

      w.RenderEndTag();
 }

 string html = sb.ToString();

Он не создает автоматически HTML-код для вас, но он помогает вам писать HTML «более OO» и поможет вам (не гарантируя) написать правильный HTML (все теги имеют закрывающие теги и т. Д.).

5 голосов
/ 05 января 2010

Как то так?

private string getHTMLString()
{
    DirectoryInfo di = new DirectoryInfo("some directory");
    FileInfo[] files = di.GetFiles("*.dll", SearchOption.AllDirectories);
    StringBuilder sb = new StringBuilder();
    sb.Append("<table>");
    foreach (FileInfo file in files)
    {
        Assembly assembly = Assembly.LoadFile(file.FullName);
        string version = assembly.GetName().Version.ToString();
        sb.AppendFormat("<tr><td>{0}</td><td>{1}</td></tr>", file.FullName, version);
    }
    sb.Append("</table>");
    return sb.ToString();

 }

Не совсем "объектно-ориентированный", но я бы сказал, что наиболее логичным.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Составлено вручную

2 голосов
/ 05 января 2010

Теги являются тегами. Вам придется их написать.

Вы можете использовать HtmlTextWriter для фактического написания, но волшебного способа избежать этого нет.

1 голос
/ 05 января 2010

Вы можете использовать XmlWriter , чтобы сделать это более OO-способом:

StringBuilder sb = new StringBuilder();
XmlWriter xmlWri = XmlWriter.Create(sb);
xmlWri.WriteStartElement("html");
{
    xmlWri.WriteStartElement("body");
    {
        xmlWri.WriteAttributeString("bgcolor", "black");

        // More html stuff
    }
    xmlWri.WriteEndElement(); // body
}
xmlWri.WriteEndElement(); // html
xmlWri.Flush();
xmlWri.Close();
string html = sb.ToString();

Редактировать: это становится довольно громоздким, и в будущем, если вы захотите изменить HTML-контент, вам придется делать это по коду. Лучшим способом является чтение предварительно отформатированного HTML-документа с заполнителями, которые сопоставляются со столбцами в таблице, поэтому все, что вам нужно, это способ перебрать все столбцы и выполнить поиск / замену по месту в HTML-документе.

1 голос
/ 05 января 2010

То, что вы делаете, кажется достаточно простым, чтобы просто сделать это вручную с помощью строкового буфера. Если бы это было более сложно, я бы предложил вам использовать шаблонизатор, такой как StringTemplate .

0 голосов
/ 12 апреля 2012

Я сейчас пишу библиотеку, которая точно решает эту проблему. Он позволяет вам создавать свой HTML с помощью инициализаторов коллекций, поэтому он может быть довольно лаконичным. Он также поддерживает стили CSS, атрибуты элементов в качестве необязательных параметров и т. Д. Он поддерживается LGPL, поэтому вы можете использовать его где угодно.

Ваш код будет выглядеть так:

private string getHTMLString()
{
    DirectoryInfo di = new DirectoryInfo("some directory");
    FileInfo[] files = di.GetFiles("*.dll", SearchOption.AllDirectories);

    var table = new Table();

    foreach (FileInfo file in files)
    {
        Assembly assembly = Assembly.LoadFile(file.FullName);
        string version = assembly.GetName().Version.ToString();

        table.Add(new Tr { new Td { file.FullName }, new Td { version } });
    }

    return table.Render();
}

HTML ++ на SourceForge .

...