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.
1: public static string FormatNamed(this string format, object source)
2: {
3: return FormatNamed(format, source, false);
4: }
5:
6: public static string FormatNamed(this string format, object source, bool ignoreNotFound)
7: {
8: if (format == null)
9: {
10: throw new ArgumentNullException("format");
11: }
12:
13: StringBuilder result = new StringBuilder(format.Length * 2);
14:
15: using (var reader = new StringReader(format))
16: {
17: StringBuilder expression = new StringBuilder();
18: int @char = -1;
19:
20: State state = State.OutsideExpression;
21: do
22: {
23: switch (state)
24: {
25: case State.OutsideExpression:
26: @char = reader.Read();
27: switch (@char)
28: {
29: case -1:
30: state = State.End;
31: break;
32: case '{':
33: state = State.OnOpenBracket;
34: break;
35: case '}':
36: state = State.OnCloseBracket;
37: break;
38: default:
39: result.Append((char)@char);
40: break;
41: }
42: break;
43: case State.OnOpenBracket:
44: @char = reader.Read();
45: switch (@char)
46: {
47: case -1:
48: throw new FormatException();
49: case '{':
50: result.Append('{');
51: state = State.OutsideExpression;
52: break;
53: default:
54: expression.Append((char)@char);
55: state = State.InsideExpression;
56: break;
57: }
58: break;
59: case State.InsideExpression:
60: @char = reader.Read();
61: switch (@char)
62: {
63: case -1:
64: throw new FormatException();
65: case '}':
66: result.Append(OutExpression(source, expression.ToString(), ignoreNotFound));
67: expression.Length = 0;
68: state = State.OutsideExpression;
69: break;
70: default:
71: expression.Append((char)@char);
72: break;
73: }
74: break;
75: case State.OnCloseBracket:
76: @char = reader.Read();
77: switch (@char)
78: {
79: case '}':
80: result.Append('}');
81: state = State.OutsideExpression;
82: break;
83: default:
84: throw new FormatException();
85: }
86: break;
87: default:
88: throw new InvalidOperationException("Invalid state.");
89: }
90: } while (state != State.End);
91: }
92:
93: return result.ToString();
94: }
95:
96: private static string OutExpression(object source, string expression, bool ignoreNotFound)
97: {
98: string format = "";
99: string orygexpression = expression;
100:
101: int colonIndex = expression.IndexOf(':');
102: if (colonIndex > 0)
103: {
104: format = expression.Substring(colonIndex + 1);
105: expression = expression.Substring(0, colonIndex);
106: }
107:
108: try
109: {
110: if (String.IsNullOrEmpty(format))
111: {
112: return (DataBinder.Eval(source, expression) ?? "").ToString();
113: }
114: return DataBinder.Eval(source, expression, "{0:" + format + "}") ?? "";
115: }
116: catch (HttpException)
117: {
118: if (!ignoreNotFound)
119: {
120: throw new FormatException();
121: }
122: else
123: {
124: return orygexpression;
125: }
126: }
127: }
128:
129: private enum State
130: {
131: OutsideExpression,
132: OnOpenBracket,
133: InsideExpression,
134: OnCloseBracket,
135: End
136: }
Ten artykuł jest widoczny także na:
ZINE.NET