【问题标题】:C# Named string parameters with Dictionary<string,string> as source? [closed]C# 以 Dictionary<string,string> 作为源的命名字符串参数? [关闭]
【发布时间】:2014-01-28 06:37:31
【问题描述】:

我想以字典的形式将命名参数传递给类似 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";

它还必须正确处理转义的大括号:

"{{ don't change this}} {{{ButChangeThis}}}" --> "{ don't change this } {Some value}"

这里似乎有一个流行的选项摘要:

http://haacked.com/archive/2009/01/04/fun-with-named-formats-string-parsing-and-edge-cases.aspx/

但是,我发现每个示例都缺少对转义括号的处理,或者除了匿名对象之外,还缺少对 IDictionary 的支持。 (那些使用 DataBinder.Eval 不能轻易修改为接受 IDictionary 而不是对象)

还有其他想法吗?

【问题讨论】:

  • 您在寻找什么样的想法?显然不是其他链接,因为它会偏离主题,您发布的代码没有展示问题(您展示了用例,但没有实现您似乎有问题),或者可能是其他什么?
  • 我猜您可能会使用 Replace 方法将特殊标记的子字符串替换为您的字典中的值
  • 看来,最简单的方法是实现有限自动化

标签: c# regex string dictionary format


【解决方案1】:

你可以试试这个有限自动机解析器:

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

【讨论】:

  • 你是个天才,它奏效了。谢谢。
猜你喜欢
  • 2013-08-28
  • 2015-03-07
  • 2014-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多