将 C# 对象渲染为 Html

发布于 2024-07-22 19:11:13 字数 973 浏览 7 评论 0原文

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

我很乐意做这样的事情:

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

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

1。 通过代码渲染:

我可以简单地在 ToHtml 方法 (C#) 中编写用于渲染 Html 的代码 - 问题是它静态。 如果您想将标题稍微移到中间,您应该更改代码。 而且,在 C# 中读取 Html 缩进非常困难。

2. 使用XSL:

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

3. 使用其他模板引擎:

编写我自己的C# -> Html 模板引擎因此将从文件 (*.template) 中读取模板,并使用反射将正确的属性插入到模板的正确位置。 ** 对于这个解决方案我们有很多可以想到的问题,例如:语法应该如何? 这件事还好吗? %名称%

%描述%
And how we can handle arrays? ** Maybe we can use an existing engine (Brail or T4-Templating)?

你喜欢哪个? 你知道什么是好的发动机吗? 目前我更喜欢第二种解决方案,但它会非常慢。

We have bunch of Domain Entities which should be rendered to an html format, which shows their detail in a pop up window.

I would be glad to do something like this:

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

but my main problem is how to do this stuff from behind.
I have 3 different answers:

1. Render By Code:

I can simply write my code for rendering the Html inside the ToHtml Method (C#) - the problem it is that it is too static. if you would like to move a little bit the header to the middle you should change code.
moreover, it is very hard to read Html indentation in C#.

2. Using XSL:

XSL Files can easily manage the Html template and using XSLT I can transform XML file to the right place of the documents.
the parser already written by someone else (just need to learn the syntax)
** for this we will need that each object could serialize to Xml. and if the object changed -> the Xml will be changed --> the xslt need to be changed too
** this will also give me the option to indent the html easily for example: adding css capabilities and\or change the html design

3. using other template engine:

Write my own C# -> Html template Engine so it will read the template from file (*.template) and will insert the right property in the right place of the template using reflection.
** For this solution we have many issues that we can think of, for example: How the syntax should be?
Is this thing ok?
%Name%

%Description%

And how we can handle arrays?
** Maybe we can use an existing engine (Brail or T4-Templating)?

What do you prefer?
Do you know a good engine?
For now I prefer the second solution, but it gonna be very slow.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

肤浅与狂妄 2024-07-29 19:11:13

我曾经需要将任何类型的集合渲染到 Html 表中。 我在 IEnumerable上创建了一个扩展方法; 它有 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();
}

I once had a need to render a collection of any type to an Html Table. I created an extension method on IEnumerable<T> that had overloads for css and the like. You can see my blog post about it here:

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

It uses reflection to get all the properties of the object, and renders a nice little table. See if that would work for you.

[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();
}
倾听心声的旋律 2024-07-29 19:11:13

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

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

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

I can't agree more with John Feminella. Integrating Html rendering directly into your domain entities is a horrid pollution of your domain with a completely arbitrary and external concern. Like John said, you will make your entities very brittle by doing that, and break both of those critical rules: Separation of Concerns and Single Responsibility.

From the choices you gave, #3 is the closest to an appropriate way to do it. You need not write your own template engine. There are plenty free and ready-made template engines on the net that will do the job more than adequately (NVelocity, StringTemplate, Brail, etc. etc.)

Keep rendering where it belongs...in your presentation/view, and don't pollute your domain with higher level concerns.

披肩女神 2024-07-29 19:11:13

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

This is the job of your view, not your controllers or models. As you suspect, using method (1) will make your changes very brittle. Instead, write a view fragment for each way in which you'd like to render a particular domain entity. Then simply pull in the appropriate views to build your final page.

挽梦忆笙歌 2024-07-29 19:11:13

我真诚地更喜欢方法 A。HTML 已经是一种标准,因此您不应该过度使用中间格式,例如 XML(通过 XSL - 方法 2)或自定义格式(方法 3)。

如果使用 ASP.NET MVC 进行编写,您可以构建一个 .ASCX(用户控件),它将接受您类型的对象并呈现适当的 HTML。 而且您不会遇到令人讨厌的 C# 缩进,也不会突出显示,也不会自动完成。

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

I sincerely prefer method A. The HTML is already a standard so you shouldn't beat yourself up too much with intermediary formats such as XML (via XSL - method 2) or a custom format (method 3).

If writing in/for ASP.NET MVC you could however build an .ASCX (user control) that would accept an object of your type and render the appropiate HTML. And you don't get the nasty C# indentation and no highlighting nor autocomplete.

You could also write multiple User views to accomodate different scenarios for one object type.

无声静候 2024-07-29 19:11:13

您是否有理由不想创建一个将域实体对象作为参数的自定义控件 .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>

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

Is there a reason you do not want to create a custom control .ascx file that takes domain entities object as an argument and then you can make the gui any way you want. This way you could dynamically add the controls to the page and just set a property to populate them.

Edit 1:
Just render the control to an HTMLTextWriter instead of placing it on the page.

        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();

Output

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

Of course use your custom control instead of a built in control but this was a quick and easy demo.

云巢 2024-07-29 19:11:13

经过一番研究后,我制作了自己的函数,将任何对象转换为 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()

它将从特定对象获取属性名称和值。 你可以根据你的情况来操作html

After bit of research i made my own function to convert Any Object toHtmlString.

VB .Net Code:

 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()

it will get the property name and value from a particular object. you can manipulate html based on your

幸福%小乖 2024-07-29 19:11:13

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

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

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

Personally, I'd combine method two and three: Just create a generic XML document using reflection, say:

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

and use an XSTL stylesheet to create the actual HTML from this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文