使用有意义的标记格式化字符串

Format string with meaningful markers

我曾经有一个模板字符串,从数据库和/或文本文件中读取:

var template="Your order {0} has dispatched from {1}, ETA {2:HH:MM dd.MM.yyyy}";

然后用string.Format(template, orderNo, warehouse, eta) 注入正确的值。

现在,做出了一项业务决策,更改这些模板以使用更有意义的标记:

var template="Your order {orderNo} has dispatched from {warehouse}, ETA {eta:HH:MM dd.MM.yyyy}";

现在我不确定注入值的最佳方式是什么,考虑到例如 eta 字段的格式是 "hardcoded" 到模板中(这样我们可以根据语言使用不同的 DateTime 格式)

一个想法是将模板加载到 StringBuilder,将命名变量替换为 {0}, {1}.. 等的集合,然后使用旧的 string.Format 方法,但它不是真正可扩展的写所有的样板文件时腰酸背痛。

var formatTemplate = new StringBuilder(template)
    .Replace("{orderNo}", "{0}")
    .Replace("{warehouse}", "{1}")
    .Replace("{eta","{2")
    .ToString();
return string.Format(template, orderNo, warehouse, eta)

有更好的方法吗?也许是一种将模板读取为内插字符串的方法?该字符串是从外部源读取的,因此我不能简单地使用 $"{marker}" 机制。

请检查 SmartFormat 哪个实际上会做你想做的事。

(你说过,你不使用索引替换人类可读的名称)

来自他们 wiki 的示例:

String.Format 按索引引用所有参数:

String.Format("{0} {1}", person.FirstName, person.LastName)

Smart.Format 更进一步,让您可以使用命名占位符:

Smart.Format("{FirstName} {LastName}", person)

其实Smart.Format支持几种表达方式:

Smart.Format("{FirstName.ToUpper} {LastName.ToLower}", person)

工作示例需要将变量打包成匿名类型:

var formatted=Smart.Format(template, new { orderNo, warehouseName, eta })

returns 正确的、期望的结果,标记已正确替换。没有匿名类型,它似乎不起作用。

如果您的框架支持,您可以使用字符串插值: 看看这个: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interpolated-strings

然后您可以像这样更新您的代码:

 var orderNo = 1;
 var warehouse = "Trinidad";
 var template = $"Your order {orderNo} has dispatched from {warehouse}";