using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.ComponentModel; using System.Security; using System.Runtime.InteropServices; using System.Net; namespace TradeIdeas.Stocks.ETrade { public static class StringExtensions { /// /// Extension method that replaces keys in a string with the values of matching object properties. /// Uses String.Format() 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 String.Format() 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 String.Format() 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) { var result = formatString; if (attributes == null || formatString == null) { return result; } return attributes.Keys.Cast().Aggregate(result, (current, attributeKey) => current.InjectSingleValue(attributeKey, attributes[attributeKey])); } /// /// 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)(?:}|(?::(.[^}]*)}))"); var 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; 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; } // http://blogs.msdn.com/b/fpintos/archive/2009/06/12/how-to-properly-convert-securestring-to-string.aspx public static string AsString(this SecureString value) { if (value == null) { return null; } IntPtr unmanagedString = IntPtr.Zero; try { unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(value); return Marshal.PtrToStringUni(unmanagedString); } finally { Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); } } public static SecureString AsSecureString(this string value) { if (string.IsNullOrEmpty(value)) { return null; } unsafe { fixed (char* passwordChars = value) { var ss = new SecureString(passwordChars, value.Length); ss.MakeReadOnly(); return ss; } } //var ss = new SecureString(); //foreach (var c in value.ToCharArray()) //{ // ss.AppendChar(c); //} //ss.MakeReadOnly; //return ss; } public static string ToDelimitedString(this IEnumerable value, string delimiter) { return string.Join(delimiter, from v in value select v); } } }