Reputation: 375
Given I have a Meta Data resource string stored in my Database that will return like this:
var pageTitle = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";
And I want to replace the {placeholders}
with variable values
;
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";
I have tried, with no luck;
var newTitle = $"pageTitle, category1, category2, category3";
var newTitle = $(pageTitle, category1, category2, category3);
I know that I could use string.Replace()
that has a performance overhead. Does anyone know how this can be done efficiently using the latest C# string interpolation?
Upvotes: 20
Views: 8742
Reputation: 1944
Please checkout my libary thats solves this problem TinyTools if you use it give me an upvote and if you like it leave a star on github.
var person = new Person
{
FirstName = "John",
LastName = "Smith"
};
var template = "Hello world, I'm {FirstName} {LastName}";
var result = template.Interpolate(person);
result.ShouldBe("Hello world, I'm John Smith");
Upvotes: 1
Reputation: 726849
Although .NET does not offer a built-in capability for this, you can easily build a pretty good implementation with regex:
public static string Format(string formatWithNames, IDictionary<string,object> data) {
int pos = 0;
var args = new List<object>();
var fmt = Regex.Replace(
formatWithNames
, @"(?<={)[^}]+(?=})"
, new MatchEvaluator(m => {
var res = (pos++).ToString();
var tok = m.Groups[0].Value.Split(':');
args.Add(data[tok[0]]);
return tok.Length == 2 ? res+":"+tok[1] : res;
})
);
return string.Format(fmt, args.ToArray());
}
The idea is to replace names with consecutive numbers (see sb.Append(pos++)
), build an array of object parameters (see args.Add(data[tok[0]])
), and pass the result to string.Format
to use string
's formatting capabilities.
Now you can pass your resource to this Format
, along with a dictionary of key-value pairs, and get a string formatted using .NET's built-in formatting capabilities:
var x = new Dictionary<string,object> {
{"brown", 1}
, {"jumps", 21}
, {"lazy", 42}
};
Console.WriteLine("{0}", Format("Quick {brown} fox {jumps:C} over the {lazy:P} dog", x));
Note that there is no $
in front of the string literal, so there's no C#'s built-in interpolation going on here.
This prints
Quick 1 fox $21.00 over the 4,200.00 % dog
The approach is based on the idea by Scott Hanselman, except formatting is done differently.
Upvotes: 11
Reputation: 152626
If you don't want to use string replacement, then you either need to use the original formatting syntax:
var pageTitle = "Shop the latest {0} Designer {1} {2} at www.abc.com";
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";
var newTitle = string.Format(pageTitle, category1, category2, category3);
or put the formatting string after the variables:
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";
var newTitle = $"Shop the latest {0} Designer {0} {0} at www.abc.com";
The string interpolation is converted to a string.Format
call at compile time, so there's no way to make the formatting string a variable at run-time.
Upvotes: 5
Reputation: 151674
I know that I could use string.Replace() that has a performance overhead
Of mere nanoseconds. You shouldn't optimize prematurely.
As said, the C# 6 string interpolation feature happens at compile-time. If you want to do this at runtime, you'll have to use string replacement.
I assume your strings are formatted like that for ease of editing and not having a fixed replacement order, so simply do this:
var input = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";
var result = input.Replace("{category1}", category1)
.Replace("{category2}", category2)
.Replace("{category3}", category3);
This will just work. You could also store your replacement values in a dictionary, and loop over the keys to replace the key with the value.
Upvotes: 18
Reputation: 157048
You can't use string interpolation here. String interpolation is a compile-time rewrite method for string.Format
, which is the solution you should use:
var newTitle = string.Format("{0}, {1}, {2}, {3}", pageTitle, category1, category2, category3);
Or string.Join
:
var newTitle - string.Join(", ", new string[] { pageTitle, category1, category2, category3 });
Since you are loading from database, it might be just better in your case to keep using string.Replace
.
Upvotes: 20