带有意义标记的格式字符串

时间:2018-03-16 12:41:51

标签: c# .net string-formatting string-interpolation

我使用过模板字符串,从DB和/或文件文件中读取:

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字段的格式是"硬编码"到模板(这样我们可以根据语言使用不同的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}"机制。

2 个答案:

答案 0 :(得分:2)

请查看SmartFormat,它实际上可以执行您想要的操作。

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

他们的wiki示例:

String.Format按索引引用所有args:

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

返回正确,期望的结果,并正确替换标记。如果没有匿名类型,它似乎无法正常工作。

答案 1 :(得分:-1)

如果您的框架支持,您可以使用字符串插值: 看看这个: 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}";