C#6.0有一个string interpolation --一个很好的格式化字符串的特性,比如:
var name = "John";
WriteLine($"My name is {name}");
该示例将转换为
var name = "John";
WriteLine(String.Format("My name is {0}", name));
从本地化的角度来看,最好像这样存储字符串:
"My name is {name} {middlename} {surname}"
而不是使用String.Format表示法:
"My name is {0} {1} {2}"
如何使用字符串插值进行.NET本地化?有没有办法把$"...“到资源文件?或者字符串应该像"...{name}“那样存储并以某种方式即时插入?
附注:这个问题不是关于“如何做string.FormatIt扩展”(有很多这样的库,所以答案,等等)。这个问题是关于“本地化”上下文中的“字符串插值”的罗斯林扩展(两者都是MS .NET词汇表中的术语),或者像迪伦提出的动态用法。
发布于 2018-04-09 13:20:01
使用Microsoft.CodeAnalysis.CSharp.Scripting包可以实现这一点。
您将需要创建一个对象来存储数据,下面使用的是动态对象。您还可以创建一个具有所有必需属性的特定类。在描述的here中将动态对象包装在类中的原因。
public class DynamicData
{
public dynamic Data { get; } = new ExpandoObject();
}
然后,您可以使用它,如下所示。
var options = ScriptOptions.Default
.AddReferences(
typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).GetTypeInfo().Assembly,
typeof(System.Runtime.CompilerServices.DynamicAttribute).GetTypeInfo().Assembly);
var globals = new DynamicData();
globals.Data.Name = "John";
globals.Data.MiddleName = "James";
globals.Data.Surname = "Jamison";
var text = "My name is {Data.Name} {Data.MiddleName} {Data.Surname}";
var result = await CSharpScript.EvaluateAsync<string>($"$\"{text}\"", options, globals);
这是编译并执行代码片段,因此这是真正的C#字符串插值。尽管你必须考虑它的性能,因为它实际上是在运行时编译和执行你的代码。如果您可以使用CSharpScript.Create编译和缓存代码,则可以避免这种性能影响。
发布于 2015-03-16 10:12:19
插值字符串将花括号之间的块计算为C#表达式(例如{expression}
,{1 + 1}
,{person.FirstName}
)。
这意味着插值字符串中的表达式必须引用当前上下文中的名称。
例如,以下语句将不会编译:
var nameFormat = $"My name is {name}"; // Cannot use *name*
// before it is declared
var name = "Fred";
WriteLine(nameFormat);
类似地:
class Program
{
const string interpolated = $"{firstName}"; // Name *firstName* does not exist
// in the current context
static void Main(string[] args)
{
var firstName = "fred";
Console.WriteLine(interpolated);
Console.ReadKey();
}
}
回答你的问题:
框架当前没有提供在运行时评估内插字符串的机制。因此,您不能在开箱即用时存储字符串和插值。
有一些库可以处理字符串的运行时插值。
发布于 2016-09-19 17:09:18
正如在前面的回答中所说的:您目前不能在运行时(例如从资源文件)加载用于字符串插值的格式字符串,因为它是在编译时使用的。
如果你不关心编译时特性,只想拥有命名的占位符,你可以使用如下的扩展方法:
public static string StringFormat(this string input, Dictionary<string, object> elements)
{
int i = 0;
var values = new object[elements.Count];
foreach (var elem in elements)
{
input = Regex.Replace(input, "{" + Regex.Escape(elem.Key) + "(?<format>[^}]+)?}", "{" + i + "${format}}");
values[i++] = elem.Value;
}
return string.Format(input, values);
}
请注意,这里不能有像{i+1}
这样的内联表达式,并且这不是具有最佳性能的代码。
您可以将其与从资源文件加载的字典一起使用,或者像这样内联:
var txt = "Hello {name} on {day:yyyy-MM-dd}!".StringFormat(new Dictionary<string, object>
{
["name"] = "Joe",
["day"] = DateTime.Now,
});
https://stackoverflow.com/questions/29068194
复制相似问题