如何为字符串格式提供自定义字符串占位符

时间:2009-07-09 07:17:57

标签: c# .net string string-formatting

我有一个字符串

string str ="Enter {0} patient name";

我正在使用string.format格式化它。

String.Format(str, "Hello");

现在如果我想要从某些配置中检索患者,那么我需要将str改为类似的东西 "Enter {0} {1} name"。所以它将用第二个值替换{1}。问题是我想要{1}而不是{1}其他格式的东西,如{pat}。但是当我尝试使用时,它会抛出一个错误。我想要一种不同格式的原因是我需要更改这么多文件(可能包含{0},{1}等)。所以我需要一个可以在运行时替换的自定义占位符。

8 个答案:

答案 0 :(得分:51)

您可能需要FormatWith 2.0查看James Newton-King。它允许您使用属性名称作为格式化标记,例如:

var user = new User()
{
    Name = "Olle Wobbla",
    Age = 25
};

Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));

您也可以将它与匿名类型一起使用。

更新: solution之后还有类似的Scott Hanselman,但它是Object上的一组扩展方法而不是{{1} }。

2012年更新:您可以NETFx String.FormatWith Extension Method

获取Calrius Consulting的NuGet.org NuGet套餐

更新2014 :还有StringFormat.NETlittlebit's StringFormat

答案 1 :(得分:17)

带有Regex

MatchEvaluator似乎是个不错的选择:

static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
static void Main()
{
    string input = "this {foo} is now {bar}.";
    StringDictionary fields = new StringDictionary();
    fields.Add("foo", "code");
    fields.Add("bar", "working");

    string output = re.Replace(input, delegate (Match match) {
        return fields[match.Groups[1].Value];
    });
    Console.WriteLine(output); // "this code is now working."
}

答案 2 :(得分:3)

我看到了上面的所有答案,然而,却无法解决问题:)

以下代码是否有任何特殊原因不符合您的要求?

string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();

string result = "Enter " + myFirstStr + " " + mySecondStr + " name";

答案 3 :(得分:3)

object[] myInts = new int[] {8,9}; 

但是你可以逃脱:

object[] myInts = new string[] { "8", "9" }; 
string bar = string.Format("{0} {1}", myInts); 

答案 4 :(得分:2)

以下是我在此处找到的另一个版本:http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1

对此的任何解决方案都将涉及反射,这不太理想,但这是他的代码解决了一些其他主要性能问题。 (没有错误检查。如果你愿意,可以添加它。):

1)使用直接运行时反射,没有DataBinder开销

2)不使用正则表达式,使用单遍解析和状态。

3)不将字符串转换为中间字符串,然后再将其转换为最终格式。

4)使用单个StringBuilder分配和连接,而不是在整个地方新建字符串并将它们连接成新的字符串。

5)删除为n个替换操作调用委托的堆栈开销。

6)一般情况下,单次传递将以相对线性的方式缩放(每个prop查找和嵌套prop prop查找仍需要一些成本,但就是这样。)

public static string FormatWith(this string format, object source)
{
    StringBuilder sbResult = new StringBuilder(format.Length);
    StringBuilder sbCurrentTerm = new StringBuilder();
    char[] formatChars = format.ToCharArray();
    bool inTerm = false;
    object currentPropValue = source;

    for (int i = 0; i < format.Length; i++)
    {
        if (formatChars[i] == '{')
            inTerm = true;
        else if (formatChars[i] == '}')
        {
            PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
            sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
            sbCurrentTerm.Clear();
            inTerm = false;
            currentPropValue = source;
        }
        else if (inTerm)
        {
            if (formatChars[i] == '.')
            {
                PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
                currentPropValue = pi.GetValue(source, null);
                sbCurrentTerm.Clear();
            }
            else
                sbCurrentTerm.Append(formatChars[i]);
        }
        else
            sbResult.Append(formatChars[i]);
    }
    return sbResult.ToString();
} 

答案 5 :(得分:1)

您还可以使用Marc Gravell中的示例并扩展String类对象:

public static class StringExtension
{
    static readonly Regex re = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
    public static string FormatPlaceholder(this string str, Dictionary<string, string> fields)
    {
        if (fields == null)
            return str;

        return re.Replace(str, delegate(Match match)
        {
            return fields[match.Groups[1].Value];
        });

    }
}

使用示例:

String str = "I bought a {color} car";
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("color", "blue");

str.FormatPlaceholder(fields));

答案 6 :(得分:0)

最好使用Replace替换自定义字段,使用Format替换其余字段,例如:

string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");

答案 7 :(得分:0)

我想要的东西更像Python的字符串格式,所以我写了这个: https://gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b

像这样使用:

Dim template = New FormatFromDictionary("{cat} vs {dog}")
Dim d = New Dictionary(Of String, Object) From {
    {"cat", "Felix"}, {"dog", "Rex"}}
Console.WriteLine(template.Replace(d)) ' Felix vs Rex