Mattman
Mattman

Reputation: 33

A better way to do replacement tags in c#?

I need a better way to do this:

Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(Regex.Replace(textMessage.Trim(), "{birthday}", person.Birthday, RegexOptions.None), "{phone}", person.MobilePhone, RegexOptions.None), "{email}", person.Email, RegexOptions.None), "{lastname}", person.LastName, RegexOptions.None), "{firstname}", person.FirstName, RegexOptions.None)

Upvotes: 2

Views: 143

Answers (3)

user166390
user166390

Reputation:

I prefer to match on say, {word} and then use the Replace overload that takes a MatchEvaluator.

Then it's easy to have a dictionary (or switch or whatever) provide the replacement input (for the given "word").

There are additional advantages such as better run-time characteristics (O(n) vs O(k*n)), scales nicely/allows separation of replacement data, and isn't affected if one of the replacements contains {} stuff.

Happy coding.


I dug this out of an old project. It looks like this even "understands" formatting. YMMV.

/// <summary>
/// Like string.Format but takes "{named}" identifiers with a Dictionary
/// of replacement values.
/// </summary>
/// <param name="format"></param>
/// <param name="replaces"></param>
/// <returns></returns>
public static string Format(string format, IDictionary<string,object> replaces) {
    if (format == null) throw new ArgumentNullException("format");
    if (replaces == null) throw new ArgumentNullException("replaces");
    return Regex.Replace(format, @"{(?<key>\w+)(?:[:](?<keyFormat>[^}]+))?}", (match) => {
        Object value;
        var key = match.Groups["key"].Value;
        var keyFormat = match.Groups["keyFormat"].Value;
        if (replaces.TryGetValue(key, out value)) {
            if (string.IsNullOrEmpty(keyFormat)) {
                return "" + value;
            } else {
                // format if applicable
                return string.Format("{0:" + keyFormat + "}", value);
            }
        } else {
            // don't replace not-found
            return match.Value;
        }
    });
}

Of course, in a more trivial manner (extracted from above, YMMV x2):

var person = GetPerson(); // I love closures
var res = Regex.Replace(input, @"{(?<key>\w+)}", (match) => {
    switch (match.Groups["key"].Value) {
        case "birthday": return person.Birthday;
        // ....
        default: return "";
    }
});

Upvotes: 2

jzila
jzila

Reputation: 735

IDictionary<string, string> replacements = new Dictionary<string, string>();
replacements.Add("{birthday}", person.Birthday);
replacements.Add("{phone}", person.MobilePhone);
...

foreach (string s in replacements.Keys) {
    Regex.Replace(textMessage, s, replacements[s], RegexOptions.None);
}

Upvotes: 3

Reza ArabQaeni
Reza ArabQaeni

Reputation: 4907

textMessage.Trim()
    .Replace("{birthday}",person.Birthday)
    .Replace("{phone}",person.Phone)
    ...

Upvotes: 6

Related Questions