34 votes

nommé String.Format, est-ce possible ?

Au lieu d'utiliser {0} {1} etc. Je veux utiliser {title} à la place. Ensuite, remplissez ces données d'une manière ou d'une autre (ci-dessous, j'ai utilisé un fichier Dictionary ). Ce code est invalide et lève une exception. Je voulais savoir si je pouvais faire quelque chose de similaire à ce que je veux. En utilisant {0 .. N} n'est pas un problème. J'étais juste curieux.

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);

1voto

jerryjvl Points 9310
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();
            });
    }
}

Cette méthode est un peu plus complexe que l'autre méthode d'extension, mais elle devrait également permettre l'utilisation de valeurs non textuelles et de modèles de formatage, comme dans votre exemple original :

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

Travaillera également...

0voto

Pavlo Neyman Points 3100

Depuis la sortie de C# 6, vous êtes en mesure d'utiliser Fonction d'interpolation des chaînes de caractères

Le code qui résout votre question :

string a = $"{d["a"]}{d["ba"]}{d["lol"]}";

0voto

Dan Sorak Points 91

Pourquoi un dictionnaire ? C'est inutile et trop compliqué. Un simple tableau à deux dimensions de paires nom/valeur fonctionnerait tout aussi bien :

public static string Format(this string formatString, string[,] nameValuePairs)
{
    if (nameValuePairs.GetLength(1) != 2)
    {
        throw new ArgumentException("Name value pairs array must be [N,2]", nameof(nameValuePairs));
    }
    StringBuilder newFormat = new StringBuilder(formatString);
    int count = nameValuePairs.GetLength(0);
    object[] values = new object[count];
    for (var index = 0; index < count; index++)
    {
        newFormat = newFormat.Replace(string.Concat("{", nameValuePairs[index,0], "}"), string.Concat("{", index.ToString(), "}"));
        values[index] = nameValuePairs[index,1];
    }
    return string.Format(newFormat.ToString(), values);
}

Appelez le numéro ci-dessus avec :

string format = "{foo} = {bar} (really, it's {bar})";
string formatted = format.Format(new[,] { { "foo", "Dictionary" }, { "bar", "unnecessary" } });

Résultats dans : "Dictionary = unnecessary (really, it's unnecessary)"

0voto

Deloo Points 66
public static string StringFormat(this string format, IDictionary<string, object> values)
{
    return Regex.Matches(format, @"\{(?!\{)(.+?)\}")
            .Select(m => m.Groups[1].Value)
            .Aggregate(format, (current, key) =>
            {
                string[] splits = key.Split(":");
                string replacement = splits.Length > 1
                    ? string.Format($"{{0:{splits[1]}}}", values[splits[0]])
                    : values[key].ToString();
                return Regex.Replace(current, "(.|^)("+ Regex.Escape($"{{{key}}}")+")(.|$)", 
                                     m => m.Groups[1].ToString() == "{" && m.Groups[3].ToString() == "}"
                                        ? m.Groups[2].ToString()
                                        : m.Groups[1] + replacement + m.Groups[3]
                                    );
            });
}

Cette réponse est similaire à une autre, mais elle considère l'échappement avec {{text}}.

-1voto

danpop Points 215

Voici une solution intéressante qui s'avère très utile pour le formatage des e-mails : http://www.c-sharpcorner.com/UploadFile/e4ff85/string-replacement-with-named-string-placeholders/

Édité :

public static class StringExtension  
{  
    public static string Format( this string str, params Expression<Func<string,object>>[] args)  
    {  
        var parameters = args.ToDictionary( e=>string.Format("{{{0}}}",e.Parameters[0].Name), e=>e.Compile()(e.Parameters[0].Name));  

        var sb = new StringBuilder(str);  
        foreach(var kv in parameters)  
        {  
            sb.Replace( kv.Key, kv.Value != null ? kv.Value.ToString() : "");  
        }  

        return sb.ToString();  
    }  
}

Exemple d'utilisation :

public string PopulateString(string emailBody)  
{  
  User person = _db.GetCurrentUser();  
  string firstName = person.FirstName;    //  Peter  
  string lastName = person.LastName;      //  Pan  
  return StringExtension.Format(emailBody.Format(  
    firstname => firstName,  
    lastname => lastName  
  ));   
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X