Can be labels used instead of numbers in String.Format?
No, they aren't by default. But it's possible by the very nice Scott Hanselman's extention method for it:
It's faster then others. Use it with objects:
No, they aren't by default. But it's possible by the very nice Scott Hanselman's extention method for it:
public static class FormattableObject { public static string ToString(this object anObject, string aFormat) { return FormattableObject.ToString(anObject, aFormat, null); } public static string ToString(this object anObject, string aFormat, IFormatProvider formatProvider) { StringBuilder sb = new StringBuilder(); Type type = anObject.GetType(); Regex reg = new Regex(@"({)([^}]+)(})",RegexOptions.IgnoreCase); MatchCollection mc = reg.Matches(aFormat); int startIndex = 0; foreach(Match m in mc) { Group g = m.Groups[2]; //it's second in the match between { and } int length = g.Index - startIndex -1; sb.Append(aFormat.Substring(startIndex,length)); string toGet = String.Empty; string toFormat = String.Empty; int formatIndex = g.Value.IndexOf(":"); //formatting would be to the right of a : if (formatIndex == -1) //no formatting, no worries { toGet = g.Value; } else //pickup the formatting { toGet = g.Value.Substring(0,formatIndex); toFormat = g.Value.Substring(formatIndex+1); } //first try properties PropertyInfo retrievedProperty = type.GetProperty(toGet); Type retrievedType = null; object retrievedObject = null; if(retrievedProperty != null) { retrievedType = retrievedProperty.PropertyType; retrievedObject = retrievedProperty.GetValue(anObject,null); } else //try fields { FieldInfo retrievedField = type.GetField(toGet); if (retrievedField != null) { retrievedType = retrievedField.FieldType; retrievedObject = retrievedField.GetValue(anObject); } } if (retrievedType != null ) //Cool, we found something { string result = String.Empty; if(toFormat == String.Empty) //no format info { result = retrievedType.InvokeMember("ToString", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase ,null,retrievedObject,null) as string; } else //format info { result = retrievedType.InvokeMember("ToString", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.IgnoreCase ,null,retrievedObject,new object[]{toFormat,formatProvider}) as string; } sb.Append(result); } else //didn't find a property with that name, so be gracious and put it back { sb.Append("{"); sb.Append(g.Value); sb.Append("}"); } startIndex = g.Index + g.Length +1 ; } if (startIndex < aFormat.Length) //include the rest (end) of the string { sb.Append(aFormat.Substring(startIndex)); } return sb.ToString(); } }
It's faster then others. Use it with objects:
Person p = new Person(); string foo = p.ToString("{Money:C} {LastName}, {ScottName} {BirthDate}");
Комментариев нет:
Отправить комментарий