【问题标题】:c# - dynamic string interpolation [duplicate]c# - 动态字符串插值
【发布时间】:2018-07-09 09:21:13
【问题描述】:

我正在尝试使用特定上下文/范围内的可用变量动态格式化某些字符串。

此字符串将包含{{parameter1}}{{parameter2}} 之类的部分,并且这些变量将存在于我将尝试重新格式化字符串的范围内。变量名应该匹配。

我寻找了一种动态字符串插值方法,或者如何使用 FormattableStringFactory,但我没有找到真正满足我需要的东西。

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{parameter2}} Today we're {{parameter1}}";
var result = MagicMethod(retrievedString, parameter1, parameter2);
// or, var result = MagicMethod(retrievedString, new { parameter1, parameter2 });

是否有现成的解决方案,或者我应该(在MagicMethod 中)将retrievedString 中的这些部分替换为作为参数给出的匿名对象的匹配成员(使用反射或类似的东西)?

编辑:

最后,我创建了一个扩展方法来处理这个问题:

internal static string SpecialFormat(this string input, object parameters) {
  var type = parameters.GetType();
  System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex( "\\{(.*?)\\}" );
  var sb = new System.Text.StringBuilder();
  var pos = 0;

  foreach (System.Text.RegularExpressions.Match toReplace in regex.Matches( input )) {
    var capture = toReplace.Groups[ 0 ];
    var paramName = toReplace.Groups[ toReplace.Groups.Count - 1 ].Value;
    var property = type.GetProperty( paramName );
    if (property == null) continue;
    sb.Append( input.Substring( pos, capture.Index - pos) );
    sb.Append( property.GetValue( parameters, null ) );
    pos = capture.Index + capture.Length;
  }

  if (input.Length > pos + 1) sb.Append( input.Substring( pos ) );

  return sb.ToString();
}

我这样称呼它:

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{parameter2} Today we're {parameter1}";
var result = retrievedString.SpecialFormat( new { parameter1, parameter2 } );

现在,我不再使用双括号了。

【问题讨论】:

  • 没有什么是 C# 的一部分,你需要一个神奇的方法。

标签: c# .net string-interpolation


【解决方案1】:

你可以使用反射和匿名类型来做到这一点:

public string StringFormat(string input, object parameters)
{
    var properties = parameters.GetType().GetProperties();
    var result = input;

    foreach (var property in properties)
    {
        result = result.Replace(
            $"{{{{{property.Name}}}}}", //This is assuming your param names are in format "{{abc}}"
            property.GetValue(parameters).ToString());
    }

    return result;
}

然后这样称呼它:

var result = StringFormat(retrievedString, new { parameter1, parameter2 });

【讨论】:

  • 嗨,DavidG,感谢您提供这种方法。如果我没有找到更“原生”的 .NET 解决方案,这正是我想要做的。我会将它与 StringBuilder 一起使用,谢谢!
【解决方案2】:

虽然不明白你遇到的困难是什么,但我赌了

Replace( string oldValue, string newValue )

你可以用你想要的数据替换你的“标签”。

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{parameter2}} Today we're {{parameter1}}";
var result = retrievedString.Replace("{{parameter2}}", parameter2).Replace({{parameter1}}, parameter1);

编辑

作者提到他正在寻找可以接受参数并迭代列表的东西。它可以通过类似的东西来完成

public static void Main(string[] args)
    {
        //your "unmodified" srting
        string text = "{{parameter2}} Today we're {{parameter1}}";

        //key = tag(explicitly) value = new string
        Dictionary<string, string> tagToStringDict = new Dictionary<string,string>();

        //add tags and it's respective replacement
        tagToStringDict.Add("{{parameter1}}", "Foo");
        tagToStringDict.Add("{{parameter2}}", "Bar");

        //this returns your "modified string"
        changeTagWithText(text, tagToStringDict);
    }

    public static string changeTagWithText(string text, Dictionary<string, string> dict)
    {
        foreach (KeyValuePair<string, string> entry in dict)
        {
            //key is the tag ; value is the replacement
            text = text.Replace(entry.Key, entry.Value);
        }
        return text;
    }

函数changeTagWithText会返回:

“今天的酒吧我们是 Foo”

使用此方法,您可以将所有标签添加到字典中,它会自动替换所有标签。

【讨论】:

  • 我假设参数和输入字符串是动态的,但这可能可以完成这项工作。
  • 您好,谢谢您的回复,问题是参数列表是可变的,所以我更喜欢使用将其作为参数并迭代列表的方法)。另一个问题是我想以一种高性能的方式来做,“string.Replace”:它不是每次都创建一个新字符串吗?
【解决方案3】:

如果您知道参数的顺序,则可以使用string.Format() 方法(msdn)。然后,您的代码将如下所示:

var parameter1 = DateTime.Now.ToString();
var parameter2 = "Hello world!";
var retrievedString = "{{0}} Today we're {{1}}";
var result = string.Format(retrievedString, parameter2, parameter1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 2017-03-23
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    相关资源
    最近更新 更多