-
-
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