7

我们有一堆域实体,它们应该呈现为 html 格式,在弹出窗口中显示它们的详细信息。

我很乐意做这样的事情:

Product product = new Product(...);
product.ToHtml();  // or: HtmlRenderer.Render(Product);

但我的主要问题是如何从后面做这些事情。我有3个不同的答案:

1. 按代码渲染:

我可以简单地编写用于在 ToHtml 方法 (C#) 中呈现 Html 的代码 - 问题在于它过于静态。如果您想将标题移动一点到中间,您应该更改代码。此外,在 C# 中很难阅读 Html 缩进。

2. 使用 XSL:

XSL Files 可以轻松管理 Html 模板,并且使用 XSLT 我可以将 XML 文件转换到文档的正确位置。已经由其他人编写的解析器(只需要学习语法)**为此,我们需要每个对象都可以序列化为 Xml。并且如果对象更改-> Xml 将更改-> xslt 也需要更改** 这也将使我可以轻松缩进 html 的选项,例如:添加 css 功能和\或更改 html 设计

3.使用其他模板引擎:

编写我自己的 C# -> Html 模板引擎,这样它将从文件 (*.template) 中读取模板,并使用反射在模板的正确位置插入正确的属性。** 在这个解决方案中,我们有很多可以想到的问题,例如:语法应该是怎样的?这东西好吗? %Name% %Description% 以及我们如何处理数组?** 也许我们可以使用现有的引擎(Brail 或 T4-Templating)?

你喜欢哪个?你知道一个好的引擎吗?现在我更喜欢第二种解决方案,但它会很慢。

谢谢

4

7 回答 7

5

我曾经需要将任何类型的集合呈现给 Html 表。我在 IEnumerable<T> 上创建了一个扩展方法,该方法具有 css 等的重载。你可以在这里看到我的博客文章:

http://crazorsharp.blogspot.com/2009/03/cool-ienumberable-extension-method_25.html

它使用反射来获取对象的所有属性,并渲染一个漂亮的小桌子。看看这是否适合你。

[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string propertiesToIncludeAsColumns = "")
{
    return ToHtmlTable(list, string.Empty, string.Empty, string.Empty, string.Empty, propertiesToIncludeAsColumns);
}

[System.Runtime.CompilerServices.Extension()]
public string ToHtmlTable<T>(IEnumerable<T> list, string tableSyle, string headerStyle, string rowStyle, string alternateRowStyle, string propertiesToIncludeAsColumns = "")
{
    dynamic result = new StringBuilder();
    if (String.IsNullOrEmpty(tableSyle)) {
        result.Append("<table id=\"" + typeof(T).Name + "Table\">");
    } else {
        result.Append((Convert.ToString("<table id=\"" + typeof(T).Name + "Table\" class=\"") + tableSyle) + "\">");
    }

    dynamic propertyArray = typeof(T).GetProperties();

    foreach (object prop in propertyArray) {
       if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
        if (String.IsNullOrEmpty(headerStyle)) {
            result.AppendFormat("<th>{0}</th>", prop.Name);
        } else {
            result.AppendFormat("<th class=\"{0}\">{1}</th>", headerStyle, prop.Name);
        }
      }
    }

    for (int i = 0; i <= list.Count() - 1; i++) {
        if (!String.IsNullOrEmpty(rowStyle) && !String.IsNullOrEmpty(alternateRowStyle)) {
            result.AppendFormat("<tr class=\"{0}\">", i % 2 == 0 ? rowStyle : alternateRowStyle);

        } else {
            result.AppendFormat("<tr>");
        }
        foreach (object prop in propertyArray) {
            if (string.IsNullOrEmpty(propertiesToIncludeAsColumns) || propertiesToIncludeAsColumns.Contains(prop.Name + ",")) {
                object value = prop.GetValue(list.ElementAt(i), null);
                result.AppendFormat("<td>{0}</td>", value ?? String.Empty);
            }
        }
        result.AppendLine("</tr>");
    }

    result.Append("</table>");

    return result.ToString();
}
于 2009-05-25T22:21:28.223 回答
3

这是您的视图的工作,而不是您的控制器或模型。正如您所怀疑的,使用方法 (1) 会使您的更改非常脆弱。相反,为您希望呈现特定域实体的每种方式编写一个视图片段。然后只需拉入适当的视图来构建您的最终页面。

于 2009-05-25T22:02:56.810 回答
3

我完全同意约翰·费米内拉的看法。将 Html 渲染直接集成到您的域实体中是对您的域的可怕污染,具有完全任意和外部的关注。就像约翰说的那样,这样做会让你的实体变得非常脆弱,并打破这两个关键规则:关注点分离和单一职责。

从您给出的选择来看,#3 是最接近合适的方法。您无需编写自己的模板引擎。网上有很多免费和现成的模板引擎可以很好地完成这项工作(NVelocity、StringTemplate、Brail 等)

在您的演示文稿/视图中继续渲染它所属的位置,并且不要用更高级别的问题污染您的域。

于 2009-05-26T02:26:06.297 回答
2

我真诚地喜欢方法 A。HTML 已经是一个标准,所以你不应该用 XML(通过 XSL - 方法 2)或自定义格式(方法 3)等中间格式来打败自己。

但是,如果写入/用于 ASP.NET MVC,您可以构建一个 .ASCX(用户控件)来接受您的类型的对象并呈现适当的 HTML。而且你不会得到讨厌的 C# 缩进,也不会突出显示或自动完成。

您还可以编写多个用户视图来适应一种对象类型的不同场景。

于 2009-05-25T22:03:50.833 回答
1

您是否有理由不想创建将域实体对象作为参数的自定义控件 .ascx 文件,然后您可以以任何您想要的方式制作 gui。通过这种方式,您可以动态地将控件添加到页面并设置一个属性来填充它们。

编辑 1: 只需将控件呈现给 HTMLTextWriter 而不是将其放置在页面上。

        StringBuilder outString = new StringBuilder();
        StringWriter outWriter = new StringWriter(outString);
        HtmlTextWriter htmlText = new HtmlTextWriter(outWriter);
        System.Web.UI.WebControls.Label lbl1 = new System.Web.UI.WebControls.Label();
        lbl1.Text = "This is just a test!";
        lbl1.ToolTip = "Really";
        lbl1.RenderControl(htmlText);
        ViewData["Output"] = outString.ToString();

输出

<span title="Really">This is just a test!</span>

当然使用您的自定义控件而不是内置控件,但这是一个快速简单的演示。

于 2009-05-25T22:06:41.170 回答
1

经过一番研究,我制作了自己的函数来将任何对象转换为 HtmlString。

VB .Net 代码:

 Public Function ToHtmlString(ByVal fObj As Object) As String
    Dim pType = fObj.GetType()
    Dim props As IList(Of PropertyInfo) = pType.GetProperties()
    Dim value As Object = Nothing
    Dim htmlString As String = "<html><body><form>"

    For Each p In props
        value = p.GetValue(fObj, Nothing)
        If value <> Nothing Then
            htmlString += String.Format("<input type=""hidden"" name=""{0}"" id=""{0}"" value=""{1}""/>", p.Name, value)
        End If
    Next

    htmlString += "</form></body></html>"
    Return htmlString.ToString()

它将从特定对象中获取属性名称和值。您可以根据您的

于 2014-03-03T02:20:16.557 回答
0

就个人而言,我会结合方法二和三:只需使用反射创建一个通用 XML 文档,例如:

<object type="xxxx">
    <property name="ttt" value="vvv"/>
    ...
</object>

并使用 XSTL 样式表从中创建实际的 HTML。

于 2009-05-26T02:02:28.263 回答