public
Last active

Updated JamesFormatter from Fun with Named Formats

  • Download Gist
JamesFormatter.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
// http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx#70316
 
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web.UI;
 
namespace StringLib
{
using System.Web;
 
public static class JamesFormatter
{
public static string JamesFormat(this string format, object source)
{
return FormatWith(format, null, source);
}
 
public static string FormatWith(this string format, IFormatProvider provider, object source)
{
if (format == null)
throw new ArgumentNullException("format");
 
List<object> values = new List<object>();
string rewrittenFormat = Regex.Replace(format,
@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+",
delegate(Match m)
{
Group startGroup = m.Groups["start"];
Group propertyGroup = m.Groups["property"];
Group formatGroup = m.Groups["format"];
Group endGroup = m.Groups["end"];
 
values.Add((propertyGroup.Value == "0")
? source
: Eval(source, propertyGroup.Value));
 
int openings = startGroup.Captures.Count;
int closings = endGroup.Captures.Count;
 
return openings > closings || openings % 2 == 0
? m.Value
: new string('{', openings) + (values.Count - 1) + formatGroup.Value
+ new string('}', closings);
},
RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
 
return string.Format(provider, rewrittenFormat, values.ToArray());
}
 
private static object Eval(object source, string expression)
{
try
{
return DataBinder.Eval(source, expression);
}
catch (HttpException e)
{
throw new FormatException(null, e);
}
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.