using System; using System.Text.RegularExpressions; using System.Collections; using System.Globalization; using System.ComponentModel; /// Source: http://mo.notono.us/2008/07/c-stringinject-format-strings-by-key.html [assembly: CLSCompliant(true)] namespace StringInject { public static class StringInjectExtension { /// /// Extension method that replaces keys in a string with the values of matching object properties. /// Uses internally; custom formats should match those used for that method. /// /// The format string, containing keys like {foo} and {foo:SomeFormat}. /// The object whose properties should be injected in the string /// A version of the formatString string with keys replaced by (formatted) key values. public static string Inject(this string formatString, object injectionObject) { return formatString.Inject(GetPropertyHash(injectionObject)); } /// /// Extension method that replaces keys in a string with the values of matching dictionary entries. /// Uses internally; custom formats should match those used for that method. /// /// The format string, containing keys like {foo} and {foo:SomeFormat}. /// An with keys and values to inject into the string /// A version of the formatString string with dictionary keys replaced by (formatted) key values. public static string Inject(this string formatString, IDictionary dictionary) { return formatString.Inject(new Hashtable(dictionary)); } /// /// Extension method that replaces keys in a string with the values of matching hashtable entries. /// Uses internally; custom formats should match those used for that method. /// /// The format string, containing keys like {foo} and {foo:SomeFormat}. /// A with keys and values to inject into the string /// A version of the formatString string with hastable keys replaced by (formatted) key values. public static string Inject(this string formatString, Hashtable attributes) { string result = formatString; if (attributes == null || formatString == null) return result; foreach (string attributeKey in attributes.Keys) { result = result.InjectSingleValue(attributeKey, attributes[attributeKey]); } return result; } /// /// Replaces all instances of a 'key' (e.g. {foo} or {foo:SomeFormat}) in a string with an optionally formatted value, and returns the result. /// /// The string containing the key; unformatted ({foo}), or formatted ({foo:SomeFormat}) /// The key name (foo) /// The replacement value; if null is replaced with an empty string /// The input string with any instances of the key replaced with the replacement value public static string InjectSingleValue(this string formatString, string key, object replacementValue) { string result = formatString; //regex replacement of key with value, where the generic key format is: //Regex foo = new Regex("{(foo)(?:}|(?::(.[^}]*)}))"); Regex attributeRegex = new Regex("{(" + key + ")(?:}|(?::(.[^}]*)}))"); //for key = foo, matches {foo} and {foo:SomeFormat} //loop through matches, since each key may be used more than once (and with a different format string) foreach (Match m in attributeRegex.Matches(formatString)) { string replacement = m.ToString(); if (m.Groups[2].Length > 0) //matched {foo:SomeFormat} { //do a double string.Format - first to build the proper format string, and then to format the replacement value string attributeFormatString = string.Format(CultureInfo.InvariantCulture, "{{0:{0}}}", m.Groups[2]); replacement = string.Format(CultureInfo.CurrentCulture, attributeFormatString, replacementValue); } else //matched {foo} { replacement = (replacementValue ?? string.Empty).ToString(); } //perform replacements, one match at a time result = result.Replace(m.ToString(), replacement); //attributeRegex.Replace(result, replacement, 1); } return result; } /// /// Creates a HashTable based on current object state. /// Copied from the MVCToolkit HtmlExtensionUtility class /// /// The object from which to get the properties /// A containing the object instance's property names and their values private static Hashtable GetPropertyHash(object properties) { Hashtable values = null; if (properties != null) { values = new Hashtable(); PropertyDescriptorCollection props = TypeDescriptor.GetProperties(properties); foreach (PropertyDescriptor prop in props) { values.Add(prop.Name, prop.GetValue(properties)); } } return values; } } }