Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

named String.Format, is it possible?

People also ask

What is the name of the string format method?

The Java String. format() method returns the formatted string by a given locale, format, and argument. If the locale is not specified in the String. format() method, it uses the default locale by calling the Locale.

Why do we use string format?

Format provides give you great flexibility over the output of the string in a way that is easier to read, write and maintain than just using plain old concatenation. Additionally, it's easier to get culture concerns right with String.

Is string format safe?

String formatting may be dangerous when a format string depends on untrusted data. So, when using str. format() or %-formatting, it's important to use static format strings, or to sanitize untrusted parts before applying the formatter function.


No, but this extension method will do it

static string FormatFromDictionary(this string formatString, Dictionary<string, string> valueDict) 
{
    int i = 0;
    StringBuilder newFormatString = new StringBuilder(formatString);
    Dictionary<string, int> keyToInt = new Dictionary<string,int>();
    foreach (var tuple in valueDict)
    {
        newFormatString = newFormatString.Replace("{" + tuple.Key + "}", "{" + i.ToString() + "}");
        keyToInt.Add(tuple.Key, i);
        i++;                    
    }
    return String.Format(newFormatString.ToString(), valueDict.OrderBy(x => keyToInt[x.Key]).Select(x => x.Value).ToArray());
}

Check this one, it supports formating:

    public static string StringFormat(string format, IDictionary<string, object> values)
    {
        var matches = Regex.Matches(format, @"\{(.+?)\}");
        List<string> words = (from Match matche in matches select matche.Groups[1].Value).ToList();

        return words.Aggregate(
            format,
            (current, key) =>
                {
                    int colonIndex = key.IndexOf(':');
                    return current.Replace(
                        "{" + key + "}",
                        colonIndex > 0
                            ? string.Format("{0:" + key.Substring(colonIndex + 1) + "}", values[key.Substring(0, colonIndex)])
                            : values[key].ToString());
                });
    }

How to use:

string format = "{foo} is a {bar} is a {baz} is a {qux:#.#} is a really big {fizzle}";
var dictionary = new Dictionary<string, object>
    {
        { "foo", 123 },
        { "bar", true },
        { "baz", "this is a test" },
        { "qux", 123.45 },
        { "fizzle", DateTime.Now }
    };
StringFormat(format, dictionary)

You can implement your own:

public static string StringFormat(string format, IDictionary<string, string> values)
{
    foreach(var p in values)
        format = format.Replace("{" + p.Key + "}", p.Value);
    return format;
}

Phil Haack discussed several methods of doing this on his blog a while back: http://haacked.com/archive/2009/01/14/named-formats-redux.aspx. I've used the "Hanselformat" version on two projects with no complaints.


It's possible now

With Interpolated Strings of C# 6.0 you can do this:

string name = "John";
string message = $"Hi {name}!";
//"Hi John!"

static public class StringFormat
{
    static private char[] separator = new char[] { ':' };
    static private Regex findParameters = new Regex(
        "\\{(?<param>.*?)\\}",
        RegexOptions.Compiled | RegexOptions.Singleline);

    static string FormatNamed(
        this string format,
        Dictionary<string, object> args)
    {
        return findParameters.Replace(
            format,
            delegate(Match match)
            {
                string[] param = match.Groups["param"].Value.Split(separator, 2);

                object value;
                if (!args.TryGetValue(param[0], out value))
                    value = match.Value;

                if ((param.Length == 2) && (param[1].Length != 0))
                    return string.Format(
                        CultureInfo.CurrentCulture,
                        "{0:" + param[1] + "}",
                        value);
                else
                    return value.ToString();
            });
    }
}

A little more involved than the other extension method, but this should also allow non-string values and formatting patterns used on them, so in your original example:

Dictionary<string, object> d = new Dictionary<string, object>();
d["a"] = DateTime.Now;
string a = string.FormatNamed("{a:yyyyMMdd-HHmmss}", d);

Will also work...