C#使用Dictionary 作为源命名字符串参数?

时间:2022-10-31 10:50:54

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();
    }
  }