I'd like pass named parameters to a String.Format -like function, in the form of a Dictionary. For example:
我想将命名参数传递给类似String.Format的函数,以字典的形式。例如:
var parameters = new Dictionary<string, string>() {
{ "Pi", "3.14"},
{ "Foo", "Bars"},
{ "Bird", "Pelican"}};
var myString = "This {Bird} weighs {Pi} {Foo}".NamedFormat(parameters);\
// Now myString = "This Pelican weighs 3.14 Bars";
It must also handle escaped curly brackets correctly:
它还必须正确处理转义的大括号:
"{{ don't change this}} {{{ButChangeThis}}}" --> "{ don't change this } {Some value}"
There seems a popular summary of options here:
这里似乎有一个流行的选项摘要:
http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx/
http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx/
However I find each example lacking in either handling of escaped brackets, or, support for an IDictionary<> in addition to anonymous objects. (Those using DataBinder.Eval can't be easily modified to accept IDictionary<> instead of object)
但是我发现每个示例都缺少对转义括号的处理,或者除了匿名对象之外还支持IDictionary <>。 (那些使用DataBinder.Eval的人不能轻易修改为接受IDictionary <>而不是object)
Any other ideas?
还有其他想法吗?
1 个解决方案
#1
2
You can try this finite automata parser:
您可以尝试这种有限自动机解析器:
public static class StringFormatExtensions {
public static String NamedFormat(this String value, IDictionary<String, String> data) {
if (String.IsNullOrEmpty(value))
return value;
StringBuilder Sb = new StringBuilder();
StringBuilder Key = new StringBuilder();
Boolean inBraces = false;
Boolean SkipClose = false;
foreach (Char Ch in value) {
if (inBraces) {
if (Ch == '{') {
if (Key.Length <= 0) {
inBraces = false;
Sb.Append('{');
}
else
Key.Append(Ch);
}
else if (Ch == '}') {
inBraces = false;
String item;
if (Object.ReferenceEquals(null, data))
throw new ArgumentNullException("data");
else if (!data.TryGetValue(Key.ToString(), out item))
throw new FormatException("Key {" + Key.ToString() + "} not found");
else if (!Object.ReferenceEquals(null, item))
Sb.Append(item.ToString());
Key.Clear();
}
else
Key.Append(Ch);
}
else if (Ch == '{') {
inBraces = true;
SkipClose = true;
}
else if (Ch == '}')
if (!SkipClose) {
Sb.Append(Ch);
SkipClose = true;
}
else
SkipClose = false;
else {
Sb.Append(Ch);
SkipClose = false;
}
}
if (inBraces)
throw new FormatException("Unclosed } in the string.");
return Sb.ToString();
}
}
#1
2
You can try this finite automata parser:
您可以尝试这种有限自动机解析器:
public static class StringFormatExtensions {
public static String NamedFormat(this String value, IDictionary<String, String> data) {
if (String.IsNullOrEmpty(value))
return value;
StringBuilder Sb = new StringBuilder();
StringBuilder Key = new StringBuilder();
Boolean inBraces = false;
Boolean SkipClose = false;
foreach (Char Ch in value) {
if (inBraces) {
if (Ch == '{') {
if (Key.Length <= 0) {
inBraces = false;
Sb.Append('{');
}
else
Key.Append(Ch);
}
else if (Ch == '}') {
inBraces = false;
String item;
if (Object.ReferenceEquals(null, data))
throw new ArgumentNullException("data");
else if (!data.TryGetValue(Key.ToString(), out item))
throw new FormatException("Key {" + Key.ToString() + "} not found");
else if (!Object.ReferenceEquals(null, item))
Sb.Append(item.ToString());
Key.Clear();
}
else
Key.Append(Ch);
}
else if (Ch == '{') {
inBraces = true;
SkipClose = true;
}
else if (Ch == '}')
if (!SkipClose) {
Sb.Append(Ch);
SkipClose = true;
}
else
SkipClose = false;
else {
Sb.Append(Ch);
SkipClose = false;
}
}
if (inBraces)
throw new FormatException("Unclosed } in the string.");
return Sb.ToString();
}
}