C#中的<appSettings>字符串插值

17

我喜欢C#的新插值语法。

我想将一个动态字符串存储在我的.config文件中的appSettings下,并对其应用插值。期望的interpolatedMessage的值为"Your User Name is SnowWhite"

如果这种方法可行将非常好。 这将帮助我保持键可以配置为任何组合。(例如:“SnowWhite is your User Name”,“User Name - SnowWhite”)

 <appSettings>
    <add key="userNameKey" value="Your User Name is {userName}" />
  </appSettings>

输入图像描述

6个回答

25

字符串插值是一种语法糖,它编译成字符串格式。这意味着它需要在编译时知道所有细节。在您的情况下,您只能在运行时知道字符串,因此需要使用字符串格式

<appSettings>
    <add key="userNameKey" value="Your User Name is {0}" />
</appSettings>

代码:

var message = string.Format(ConfigurationManager["userNameKey"], userName);

7

使用插值字符串无法完成此操作。插值字符串中使用的变量应在编译时已知。然而,您可以使用string.Format来实现您想要的效果。

var result = string.Format(message, userName);

并将消息的值更改为以下内容:

 <add key="userNameKey" value="Your User Name is {0}" />

3
插值字符串在编译时被转换为等效的string.Format。因此,上述代码将无法正常工作,因为该字符串是在运行时检索的。

1
我还错过了在配置文件中更易读的字符串的行为。因此,我在字符串上创建了一个扩展方法。
public static class StringExtensions
{
    public static string Interpolate(this string self, object interpolationContext)
    {
        var placeholders = Regex.Matches(self, @"\{(.*?)\}");
        foreach (Match placeholder in placeholders)
        {
            var placeholderValue = placeholder.Value;
            var placeholderPropertyName = placeholderValue.Replace("{", "").Replace("}", "");
            var property = interpolationContext.GetType().GetProperty(placeholderPropertyName);
            var value = property?.GetValue(interpolationContext)?.ToString() ?? "";
            self = self.Replace(placeholderValue, value);
        }
        return self;
    }
}

并像这样使用它
    [Fact]
    public void Foo()
    {
        var world = "World";
        var someInt = 42;
        var unused = "Not used";

        //This is a normal string, it can be retrieved from config
        var myString = "Hello {world}, this is {someInt}";

        //You need to pass all local values that you may be using in your string interpolation. Pass them all as one single anonymous object.
        var result = myString.Interpolate(new {world, someInt, unused});

        result.Should().Be("Hello World, this is 42");
    }

编辑: 对于点表示法的支持: 感谢这个答案

public static class StringExtensions
{
    public static string Interpolate(this string self, object interpolationContext)
    {
        var placeholders = Regex.Matches(self, @"\{(.*?)\}");
        foreach (Match placeholder in placeholders)
        {
            var placeholderValue = placeholder.Value;
            var placeholderPropertyName = placeholderValue.Replace("{", "").Replace("}", "");
            var value = GetPropertyValue(interpolationContext, placeholderPropertyName)?.ToString() ?? "";
            self = self.Replace(placeholderValue, value);
        }
        return self;
    }

    public static object GetPropertyValue(object src, string propName)
    {
        if (src == null) throw new ArgumentException("Value cannot be null.", nameof(src));
        if (propName == null) throw new ArgumentException("Value cannot be null.", nameof(propName));

        if (propName.Contains("."))
        {
            var temp = propName.Split(new char[] {'.'}, 2);
            return GetPropertyValue(GetPropertyValue(src, temp[0]), temp[1]);
        }
        var prop = src.GetType().GetProperty(propName);
        return prop != null ? prop.GetValue(src, null) : null;

    }
}

1

正如其他人所提到的,您无法在此情况下使用插值。但是这个怎么样?

string userName = "SnowWhite";
var message = ConfigurationManager.AppSettings["userNameKey"];
message = message.Replace("{userName}", userName);

0
对我来说,将插值字符串转换为格式化字符串,然后使用普通的 string.format 更简单。
private static string ConvertInterpolatedStringToFormartString(string interpolatedString)
{
   var placeholders = Regex.Matches(interpolatedString, @"\{(.*?)\}").ToArray();
   for (int i = 0; i < placeholders.Length; i++)
   {                    
       interpolatedString = interpolatedString.Replace(placeholders[i].ToString(), $"{{{i}}}");
   }
        return interpolatedString;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接