如何将 VB.Net 12 中的多行附加合并到一个 AppendFormat 中
How can I combine multi line appends in VB.Net 12 into a single AppendFormat
我正在使用 VB.Net 12,因此在 C# 中不允许使用多行字符串。
我在 VB.Net 中有以下代码,我需要将其转换为单个 AppendFormat
。这在 C# 中非常容易,因为长字符串可以分布在多行中以获得更好的 readability/maintenance,但在 VB.Net 中似乎不可能不使用 &
运算符连接字符串;但随后使用 StringBuilder 的目的就落空了。
问题
我可以在不使用字符串连接运算符 &
的情况下将以下 VB.Net 转换为使用单个 AppendFormat
吗?
'use a stringbuilder for better string performance
Dim sb As New StringBuilder()
sb.Append("<html>")
sb.Append("<head><style>body {font-size:10pt; font-family:Arial, Sans Serif;} table{margin:0; padding:0; border-collapse:collapse;} td{border:solid 1px #eee; padding:2px;}")
sb.Append(".m{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;} .t{width:120px; font-weight:bold; font-size:8pt;} .d{width:500px;}")
sb.Append("</style></head>")
sb.Append("<body>")
sb.AppendFormat("<div class='m'> {0} </div><table>", ex.Message.ToString())
sb.AppendFormat("<tr><td class='t'>REQUEST URL</td><td class='d'> {0} </td></tr>", currentContext.Request.Url.OriginalString)
sb.AppendFormat("<tr><td class='t'>REQUEST PATH</td><td class='d'> {0} </td></tr>", currentContext.Request.Path)
sb.AppendFormat("<tr><td class='t'>QUERY STRING</td><td class='d'> {0} </td></tr>", currentContext.Request.QueryString.ToString())
sb.AppendFormat("<tr><td class='t'>TARGET SITE</td><td class='d'> {0} </td></tr>", ex.TargetSite.Name)
sb.AppendFormat("<tr><td class='t'>STACK TRACE</td><td class='d'> {0} </td></tr>", ex.StackTrace)
sb.AppendFormat("<tr><td class='t'>USERID</td><td class='d'> {0} </td></tr>", userId)
sb.AppendFormat("<tr><td class='t'>USER</td><td class='d'> {0} </td></tr>", userName)
sb.Append("</table>")
sb.Append("</body>")
sb.Append("</html>")
更新
我使用史蒂夫的回答让它工作,他建议使用 XML 元素。我唯一需要做的就是通过在表达式中的每个花括号前加上相同的花括号来转义花括号。工作代码如下。
Dim s As XElement = <html>
<head>
<style>
body{{font-size:10pt; font-family:Arial, Sans Serif;}}
table{{margin:0; padding:0; border-collapse:collapse;}}
td{{border:solid 1px #eee; padding:2px;}}
.m{{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;}}
.t{{width:120px; font-weight:bold; font-size:8pt;}}
.d{{width:500px;}}
</style>
</head>
<body>
<div class='m'>{0}</div>
<table>
<tr><td class='t'>REQUEST URL</td><td class='d'>{1}</td></tr>
<tr><td class='t'>REQUEST PATH</td><td class='d'>{2}</td></tr>"
<tr><td class='t'>QUERY STRING</td><td class='d'>{3}</td></tr>"
<tr><td class='t'>TARGET SITE</td><td class='d'>{4}</td></tr>
<tr><td class='t'>STACK TRACE</td><td class='d'>{5}</td></tr>
<tr><td class='t'>USERID</td><td class='d'>{6}</td></tr>
<tr><td class='t'>USER</td><td class='d'>{7}</td></tr>
</table>
</body>
</html>
email.Body = sb.AppendFormat(s.ToString(), ex.Message.ToString(), _
currentContext.Request.Url.OriginalString, _
currentContext.Request.Path, _
currentContext.Request.QueryString.ToString(), _
ex.TargetSite.Name, ex.StackTrace, userId, userName).ToString()
性能更新
我尝试了此处讨论的所有 3 种方法,以确定哪种方法最适合我的场景。因此,我 运行 我的 ASP.Net 场景中的每一种方法(每个测试只实施了一种)
- 测试 1:具有 StringBuiler.Format
的 XElement
- 测试 2:具有内联表达式的 XElement
- 测试 3:具有多个 Appends 和 AppendFormat 的 StringBuilder,如我问题中给出的代码
我发现每个 运行 使用 Stopwatch 对象经过的刻度数如下。每种方法我 运行 我的 ASP.Net 情景 4 次。 而且似乎StringBuilder 的第三种方法是最快的。
- 测试 1:具有 StringBuilder 格式的 XElement:6505、657、426、446
- 测试 2:具有内联表达式的 XElement:6326、414、422、635
- 测试 3:StringBuilder appends/appendformats:6588、351,345、280
我认为当有人 reading/maintaining 您的代码时 XElement 提供更好的可读性,但 XElement 方法在性能上无法击败 StringBuilder。
这里是你的代码XML Literals。我试图直接使用一个字符串,但由于某种原因,结果被截断并且原始文本的某些部分丢失了。但是使用 XElement 它可以正常工作
Dim s As XElement =
<html>
<head>
<style>
body {font-size:10pt; font-family:Arial, Sans Serif;}
table {margin:0; padding:0; border-collapse:collapse;}
td{border:solid 1px #eee; padding:2px;}
.m{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;}
.t{width:120px; font-weight:bold; font-size:8pt;}
.d{width:500px;}
</style>
</head>
<body>
<div class='m'><%= ex.Message %></div>
<table>
<tr>
<td class='t'>REQUEST URL</td>
<td class='d'><%= currentContext.Request.Url.OriginalString %></td>
</tr>
<tr>
<td class='t'>REQUEST PATH</td>
<td class='d'><%= currentContext.Request.Path %></td>
</tr>
<tr>
<td class='t'>QUERY STRING</td>
<td class='d'><%= currentContext.Request.QueryString.ToString() %></td>
</tr>
<tr>
<td class='t'>TARGET SITE</td>
<td class='d'><%= ex.TargetSite.Name %></td>
</tr>
<tr>
<td class='t'>STACK TRACE</td>
<td class='d'><%= ex.StackTrace %></td>
</tr>
<tr>
<td class='t'>USERID</td>
<td class='d'><%= userId %></td>
</tr>
<tr>
<td class='t'>USER</td>
<td class='d'><%= userName %></td>
</tr>
</table>
</body>
</html>
我们可以在样式块中用双花括号把大括号括起来,然后用string.Format替换参数。 (部分块取自上面的代码)
....
body {{font-size:10pt; font-family:Arial, Sans Serif;}}
....
此时我们可以使用String.Format来解析整个文本格式背后的代码
Dim text = String.Format(s.ToString(), ex.Message, .........)
我正在使用 VB.Net 12,因此在 C# 中不允许使用多行字符串。
我在 VB.Net 中有以下代码,我需要将其转换为单个 AppendFormat
。这在 C# 中非常容易,因为长字符串可以分布在多行中以获得更好的 readability/maintenance,但在 VB.Net 中似乎不可能不使用 &
运算符连接字符串;但随后使用 StringBuilder 的目的就落空了。
问题
我可以在不使用字符串连接运算符 &
的情况下将以下 VB.Net 转换为使用单个 AppendFormat
吗?
'use a stringbuilder for better string performance
Dim sb As New StringBuilder()
sb.Append("<html>")
sb.Append("<head><style>body {font-size:10pt; font-family:Arial, Sans Serif;} table{margin:0; padding:0; border-collapse:collapse;} td{border:solid 1px #eee; padding:2px;}")
sb.Append(".m{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;} .t{width:120px; font-weight:bold; font-size:8pt;} .d{width:500px;}")
sb.Append("</style></head>")
sb.Append("<body>")
sb.AppendFormat("<div class='m'> {0} </div><table>", ex.Message.ToString())
sb.AppendFormat("<tr><td class='t'>REQUEST URL</td><td class='d'> {0} </td></tr>", currentContext.Request.Url.OriginalString)
sb.AppendFormat("<tr><td class='t'>REQUEST PATH</td><td class='d'> {0} </td></tr>", currentContext.Request.Path)
sb.AppendFormat("<tr><td class='t'>QUERY STRING</td><td class='d'> {0} </td></tr>", currentContext.Request.QueryString.ToString())
sb.AppendFormat("<tr><td class='t'>TARGET SITE</td><td class='d'> {0} </td></tr>", ex.TargetSite.Name)
sb.AppendFormat("<tr><td class='t'>STACK TRACE</td><td class='d'> {0} </td></tr>", ex.StackTrace)
sb.AppendFormat("<tr><td class='t'>USERID</td><td class='d'> {0} </td></tr>", userId)
sb.AppendFormat("<tr><td class='t'>USER</td><td class='d'> {0} </td></tr>", userName)
sb.Append("</table>")
sb.Append("</body>")
sb.Append("</html>")
更新
我使用史蒂夫的回答让它工作,他建议使用 XML 元素。我唯一需要做的就是通过在表达式中的每个花括号前加上相同的花括号来转义花括号。工作代码如下。
Dim s As XElement = <html>
<head>
<style>
body{{font-size:10pt; font-family:Arial, Sans Serif;}}
table{{margin:0; padding:0; border-collapse:collapse;}}
td{{border:solid 1px #eee; padding:2px;}}
.m{{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;}}
.t{{width:120px; font-weight:bold; font-size:8pt;}}
.d{{width:500px;}}
</style>
</head>
<body>
<div class='m'>{0}</div>
<table>
<tr><td class='t'>REQUEST URL</td><td class='d'>{1}</td></tr>
<tr><td class='t'>REQUEST PATH</td><td class='d'>{2}</td></tr>"
<tr><td class='t'>QUERY STRING</td><td class='d'>{3}</td></tr>"
<tr><td class='t'>TARGET SITE</td><td class='d'>{4}</td></tr>
<tr><td class='t'>STACK TRACE</td><td class='d'>{5}</td></tr>
<tr><td class='t'>USERID</td><td class='d'>{6}</td></tr>
<tr><td class='t'>USER</td><td class='d'>{7}</td></tr>
</table>
</body>
</html>
email.Body = sb.AppendFormat(s.ToString(), ex.Message.ToString(), _
currentContext.Request.Url.OriginalString, _
currentContext.Request.Path, _
currentContext.Request.QueryString.ToString(), _
ex.TargetSite.Name, ex.StackTrace, userId, userName).ToString()
性能更新
我尝试了此处讨论的所有 3 种方法,以确定哪种方法最适合我的场景。因此,我 运行 我的 ASP.Net 场景中的每一种方法(每个测试只实施了一种)
- 测试 1:具有 StringBuiler.Format 的 XElement
- 测试 2:具有内联表达式的 XElement
- 测试 3:具有多个 Appends 和 AppendFormat 的 StringBuilder,如我问题中给出的代码
我发现每个 运行 使用 Stopwatch 对象经过的刻度数如下。每种方法我 运行 我的 ASP.Net 情景 4 次。 而且似乎StringBuilder 的第三种方法是最快的。
- 测试 1:具有 StringBuilder 格式的 XElement:6505、657、426、446
- 测试 2:具有内联表达式的 XElement:6326、414、422、635
- 测试 3:StringBuilder appends/appendformats:6588、351,345、280
我认为当有人 reading/maintaining 您的代码时 XElement 提供更好的可读性,但 XElement 方法在性能上无法击败 StringBuilder。
这里是你的代码XML Literals。我试图直接使用一个字符串,但由于某种原因,结果被截断并且原始文本的某些部分丢失了。但是使用 XElement 它可以正常工作
Dim s As XElement =
<html>
<head>
<style>
body {font-size:10pt; font-family:Arial, Sans Serif;}
table {margin:0; padding:0; border-collapse:collapse;}
td{border:solid 1px #eee; padding:2px;}
.m{color:#f00; font-weight:bold; font-size:14pt; margin-bottom:9px;}
.t{width:120px; font-weight:bold; font-size:8pt;}
.d{width:500px;}
</style>
</head>
<body>
<div class='m'><%= ex.Message %></div>
<table>
<tr>
<td class='t'>REQUEST URL</td>
<td class='d'><%= currentContext.Request.Url.OriginalString %></td>
</tr>
<tr>
<td class='t'>REQUEST PATH</td>
<td class='d'><%= currentContext.Request.Path %></td>
</tr>
<tr>
<td class='t'>QUERY STRING</td>
<td class='d'><%= currentContext.Request.QueryString.ToString() %></td>
</tr>
<tr>
<td class='t'>TARGET SITE</td>
<td class='d'><%= ex.TargetSite.Name %></td>
</tr>
<tr>
<td class='t'>STACK TRACE</td>
<td class='d'><%= ex.StackTrace %></td>
</tr>
<tr>
<td class='t'>USERID</td>
<td class='d'><%= userId %></td>
</tr>
<tr>
<td class='t'>USER</td>
<td class='d'><%= userName %></td>
</tr>
</table>
</body>
</html>
我们可以在样式块中用双花括号把大括号括起来,然后用string.Format替换参数。 (部分块取自上面的代码)
....
body {{font-size:10pt; font-family:Arial, Sans Serif;}}
....
此时我们可以使用String.Format来解析整个文本格式背后的代码
Dim text = String.Format(s.ToString(), ex.Message, .........)