c# - 动态字符串插值
c# - dynamic string interpolation
我正在尝试使用特定 context/scope 中的可用变量动态格式化一些字符串。
此字符串将包含 {{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 } );
现在,我不再使用双括号了。
你可以使用反射和匿名类型来做到这一点:
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 });
虽然不明白你遇到的困难是什么,但我赌
Replace( string oldValue, string newValue )
您可以用您想要的数据替换您的"tags"。
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
将return:
"Bar Today we're Foo"
使用此方法,您可以将所有标签添加到词典中,它会自动替换所有标签。
如果你知道参数的顺序,你可以使用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);
我正在尝试使用特定 context/scope 中的可用变量动态格式化一些字符串。
此字符串将包含 {{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 } );
现在,我不再使用双括号了。
你可以使用反射和匿名类型来做到这一点:
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 });
虽然不明白你遇到的困难是什么,但我赌
Replace( string oldValue, string newValue )
您可以用您想要的数据替换您的"tags"。
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
将return:
"Bar Today we're Foo"
使用此方法,您可以将所有标签添加到词典中,它会自动替换所有标签。
如果你知道参数的顺序,你可以使用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);