Reputation: 616
I am liking the new Interpolation syntax of C#.
I want to store a dynamic string in my .config file under appSettings
and apply interpolation on it. The expected value of interpolatedMessage
is "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. (e.g. "SnowWhite is your User Name", "User Name - SnowWhite")
<appSettings>
<add key="userNameKey" value="Your User Name is {userName}" />
</appSettings>
Upvotes: 17
Views: 8070
Reputation: 169
To me, it's simpler to convert the interpolated string into a format string and then use the normal 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;
}
Upvotes: 0
Reputation: 1988
I also missed the behavior of more readable strings in config. So I create an extension method on 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;
}
}
Upvotes: 1
Reputation: 37299
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);
Upvotes: 25
Reputation: 53958
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
,
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}" />
Upvotes: 7
Reputation: 5899
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);
Upvotes: 2
Reputation: 62213
Interpolated strings are converted at compile time into the equivalent of string.Format
. So the above will not work as the string is retrieved at run time.
Upvotes: 4