-
-
Save dotnetchris/2170953 to your computer and use it in GitHub Desktop.
| // http://haacked.com/archive/2009/01/14/named-formats-redux.aspx#70485 | |
| using System; | |
| using System.Text; | |
| using System.Web; | |
| using System.Web.UI; | |
| namespace StringLib | |
| { | |
| public static class HenriFormatter | |
| { | |
| public static string HenriFormat(this string format, object source) | |
| { | |
| if (format == null) | |
| throw new ArgumentNullException("format"); | |
| var result = new StringBuilder(format.Length * 2); | |
| var expression = new StringBuilder(); | |
| var e = format.GetEnumerator(); | |
| while (e.MoveNext()) | |
| { | |
| var ch = e.Current; | |
| if (ch == '{') | |
| { | |
| while (true) | |
| { | |
| if (!e.MoveNext()) | |
| throw new FormatException(); | |
| ch = e.Current; | |
| if (ch == '}') | |
| { | |
| result.Append(OutExpression(source, expression.ToString())); | |
| expression.Length = 0; | |
| break; | |
| } | |
| if (ch == '{') | |
| { | |
| result.Append(ch); | |
| break; | |
| } | |
| expression.Append(ch); | |
| } | |
| } | |
| else if (ch == '}') | |
| { | |
| if (!e.MoveNext() || e.Current != '}') | |
| throw new FormatException(); | |
| result.Append('}'); | |
| } | |
| else | |
| { | |
| result.Append(ch); | |
| } | |
| } | |
| return result.ToString(); | |
| } | |
| private static string OutExpression(object source, string expression) | |
| { | |
| string format = "{0}"; | |
| int colonIndex = expression.IndexOf(':'); | |
| if (colonIndex > 0) | |
| { | |
| format = "{0:" + expression.Substring(colonIndex + 1) + "}"; | |
| expression = expression.Substring(0, colonIndex); | |
| } | |
| try | |
| { | |
| if (String.IsNullOrEmpty(format)) | |
| { | |
| if (source is RouteData) | |
| source = ((RouteData) (source)).Values; | |
| var dict = source as IDictionary<string, object>; | |
| return dict != null ? dict[expression].ToString() : (DataBinder.Eval(source, expression) ?? "").ToString(); | |
| } | |
| return DataBinder.Eval(source, expression, "{0:" + format + "}") ?? ""; | |
| } | |
| catch (HttpException) | |
| { | |
| throw new FormatException(); | |
| } | |
| } | |
| } | |
| } |
You may consider changing the last parameter to 'Eval' from "{0:" + format + "}" to just 'format' at line 82. It doesn't compile the way it is
@isamochernov are you targeting the full .NET4 profile? This the exact file I'm using.
Mm, I wasn't precise, the file gets compiled. I just got format exception when I tried to run it across tests.
Please check - you set 'string format = "{0}"' at line 63 and then since it is never empty, the last parameter for DataBinder.Eval becomes {0:{0}} which is definitely not what we want it to be.
Strange, but I think too that line #82 should be return DataBinder.Eval(source, expression, format) ?? "";. Simply running "Hi {name}!".HenriFormat(new { name = "Henri" }) throws a FormatException.
Debugging to line #82 the value of the "{0:" + format + "}" expression becomes this: "{0:{0}}"
(on .net 4.5.2)
After the change both of these pass, so format parameters are respected:
"Hi {name}!".HenriFormat(new { name = "Henri" }).Should().Be("Hi Henri!");
"{data:yyyy.MM}".HenriFormat(new { data = new DateTime(2015, 2, 1) }).Should().Be("2015.02");btw do you still use it after several years?
@AkosLukacs github notifications are pretty stupid and just flood noise instead of actual important ones. I was using this around the time you posted. I haven't used it this year as i've been doing very high performance webscale development, generally trying to avoid string manipulation entirely.
Add support for anonymous object, RouteData, and RouteValueDictionary