Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Updated HenriFormatter from Named Formats Redux
// 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();
}
}
}
}
Owner

dotnetchris commented Mar 23, 2012

Add support for anonymous object, RouteData, and RouteValueDictionary

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

Owner

dotnetchris commented Jun 2, 2012

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

Owner

dotnetchris commented Jan 26, 2016

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment