简体   繁体   English

C# 字符串插值<appsettings></appsettings>

[英]C# String Interpolation on <appSettings>

I am liking the new Interpolation syntax of C#.我喜欢 C# 的新插值语法。

I want to store a dynamic string in my.config file under appSettings and apply interpolation on it.我想在appSettings下的 my.config 文件中存储一个动态字符串,并对其应用插值。 The expected value of interpolatedMessage is "Your User Name is SnowWhite" interpolatedMessage的预期值为"Your User Name is SnowWhite"

It would be great if this is possible.如果可能的话,那就太好了。 This will help me to keep the key to be configurable to any combination.这将帮助我保持密钥可配置为任何组合。 (eg "SnowWhite is your User Name", "User Name - SnowWhite") (例如“SnowWhite 是您的用户名”、“用户名 - SnowWhite”)

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

在此处输入图像描述

String interpolation is a syntax sugar that compiles to string format It means it needs to know all the details at compile time. 字符串插值是一种编译为字符串格式的语法糖,这意味着它需要在编译时知道所有细节。 In your case you only know the strings in run time and thus you need to use string format : 在您的情况下,您只知道运行时的字符串,因此您需要使用字符串格式

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

Code: 码:

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

This cannot be done using interpolated strings. 使用插值字符串无法完成此操作。 The variables used in an interpolated string should be known at the compile time. 插值字符串中使用的变量应在编译时知道。 However, you could achieve that you want using string.Format , 但是,你可以使用string.Format实现你想要的,

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

and changing the value of the message to the following one: 并将消息的值更改为以下值:

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

Interpolated strings are converted at compile time into the equivalent of string.Format . 插值字符串在编译时转换为string.Format的等效字符串。 So the above will not work as the string is retrieved at run time . 因此,上述操作无效,因为在运行时检索字符串。

I also missed the behavior of more readable strings in config. 我也错过了配置中更易读的字符串的行为。 So I create an extension method on string. 所以我在string上创建了一个扩展方法。

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

And use it like 并使用它

    [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");
    }

EDIT: For dotted notation support: Credits go to this answer . 编辑:对于虚线符号支持:积分转到这个答案

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;

    }
}

You can't use interpolation in this case as others mentioned. 在这种情况下,您不能像其他人提到的那样使用插值。 But what about this? 但是这个怎么样?

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

To me, it's simpler to convert the interpolated string into a format string and then use the normal string.format.对我来说,将内插字符串转换为格式字符串然后使用普通的 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM