views:

530

answers:

5

Instead of using {0} {1}, etc. I want to use {title} instead. Then fill that data in somehow (below i used a dictionary). This code is invalid and throws an exception. I wanted to know if i can do something similar to what i want. Using {0 .. N} is not a problem. I was just curious.

    Dictionary<string, string> d = new Dictionary<string, string>();
    d["a"] = "he";
    d["ba"] = "llo";
    d["lol"] = "world";
    string a = string.Format("{a}{ba}{lol}", d);
A: 

(your Dictionary + foreach + string.Replace) wrapped in a sub-routine or extension method?

Obviously unoptimized, but...

micahtan
A: 

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;
}
eulerfx
This loses a lot of the functionality of String.Format though.
Craig
+6  A: 

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());
}
LPCRoy
A: 
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...

jerryjvl
A: 

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.

Sean Carpenter