25 stycznia 2010, 00:43
dario
Komentarze (0)
tip
Łukasz Kurzyniec wspomniał o bardzo fajnym sposobie formatowania stringa, gdzie zamiast kolejnych indeksów {0}, {1}, itd podaje się nazwy właściwości, a jako źródło obiekt je posiadający. Niestety nie mogłem dodać komentarza na blogu Łukasza, stąd ten post. Swego czasu Phill Haack zainteresował się tym tematem i pokazał inne implementacje. Obecnie dzięki Niemu używam implementacji Henri'ego, która to mimo większej ilości kodu okazała się najszybsza.
Dodatkowo w swojej implementacji dodałem jedno przeciążenie, dzięki któremu możemy określi czy brak właściwości odpowiadającej znalezionemu parametrowi ma wyrzucić wyjątek czy też nie. Przydatne przy bardziej zaawansowanym formatowaniu/parsowaniu.
Poniżej przeklejam kod, aby nigdzie się nie zgubił ;) Acha, u mnie ta metoda nazywa się FormatNamed.
public static string FormatNamed(this string format, object source)
{
return FormatNamed(format, source, false);
}
public static string FormatNamed(this string format, object source, bool ignoreNotFound)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
StringBuilder result = new StringBuilder(format.Length * 2);
using (var reader = new StringReader(format))
{
StringBuilder expression = new StringBuilder();
int @char = -1;
State state = State.OutsideExpression;
do
{
switch (state)
{
case State.OutsideExpression:
@char = reader.Read();
switch (@char)
{
case -1:
state = State.End;
break;
case '{':
state = State.OnOpenBracket;
break;
case '}':
state = State.OnCloseBracket;
break;
default:
result.Append((char)@char);
break;
}
break;
case State.OnOpenBracket:
@char = reader.Read();
switch (@char)
{
case -1:
throw new FormatException();
case '{':
result.Append('{');
state = State.OutsideExpression;
break;
default:
expression.Append((char)@char);
state = State.InsideExpression;
break;
}
break;
case State.InsideExpression:
@char = reader.Read();
switch (@char)
{
case -1:
throw new FormatException();
case '}':
result.Append(OutExpression(source, expression.ToString(), ignoreNotFound));
expression.Length = 0;
state = State.OutsideExpression;
break;
default:
expression.Append((char)@char);
break;
}
break;
case State.OnCloseBracket:
@char = reader.Read();
switch (@char)
{
case '}':
result.Append('}');
state = State.OutsideExpression;
break;
default:
throw new FormatException();
}
break;
default:
throw new InvalidOperationException("Invalid state.");
}
} while (state != State.End);
}
return result.ToString();
}
private static string OutExpression(object source, string expression, bool ignoreNotFound)
{
string format = "";
string orygexpression = expression;
int colonIndex = expression.IndexOf(':');
if (colonIndex > 0)
{
format = expression.Substring(colonIndex + 1);
expression = expression.Substring(0, colonIndex);
}
try
{
if (String.IsNullOrEmpty(format))
{
return (DataBinder.Eval(source, expression) ?? "").ToString();
}
return DataBinder.Eval(source, expression, "{0:" + format + "}") ?? "";
}
catch (HttpException)
{
if (!ignoreNotFound)
{
throw new FormatException();
}
else
{
return orygexpression;
}
}
}
private enum State
{
OutsideExpression,
OnOpenBracket,
InsideExpression,
OnCloseBracket,
End
}
de7ce60c-0234-4210-873a-37894ebb3643|0|.0
Tagi: tip
Tip