2009-06-18 9 views
27

En lugar de usar {0} {1}, etc. En su lugar, quiero usar {title}. Luego complete esos datos de alguna manera (a continuación utilicé un Dictionary). Este código no es válido y arroja una excepción. Quería saber si puedo hacer algo similar a lo que quiero. Usar {0 .. N} no es un problema. Solo tenía curiosidad.llamado String.Format, ¿es posible?

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

Vea también: http://stackoverflow.com/questions/1322037/how-can-i-create-a-more-user-friendly-string-format-syntax/1322103#1322103 –

Respuesta

-2

(su Dictionary + foreach + string.Replace) envuelto en una sub-rutina o método de extensión?

Obviamente no optimizado, pero ...

3

Usted puede implementar su propio:

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

Esto pierde una gran cantidad de funcionalidad de String.Format sin embargo. – Craig

+0

Tenga en cuenta que con esta función no puede repetir la tecla varias veces. Ejemplo, 'Hola, {{Name}}, ¿tu nombre es realmente {{Name}}?' – Fred

14

No, pero este método de extensión lo hará

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()); 
} 
+4

Ten cuidado, tener "{{thing}}" en 'formatString' y reemplazar una clave llamada" thing "en' ValueDict' "cosa" en la cadena para un número. – Juan

+0

Esto funcionó bien. A ReSharper no le gustó lanzar la cuerda al objeto, así que cambié tu diccionario a una cadena, un par de objetos. Además, un pequeño detalle, pero no estoy de acuerdo con que un par de valores clave sea una tupla. No es realmente una lista ordenada de cosas. El ValueDict es más una tupla que nada. – JDPeckham

1
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(); 
      }); 
    } 
} 

Un poco más involucrado en comparación con el otro método de extensión, pero esto también debería permitir valores que no sean cadenas y patrones de formateo utilizados en ellos, por lo que en nuestro ejemplo inicial:

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

también trabajará ...

3

Phil Haack discuten varios métodos de hacer esto en su blog hace un tiempo: http://haacked.com/archive/2009/01/14/named-formats-redux.aspx. He usado la versión de "Hanselformat" en dos proyectos sin quejas.

+0

También me gustó el formateador Hansel. No depende de System.Web, como otros formateadores, lo cual es ideal para insertarlo en mi biblioteca de utilidades. Me gusta que pueda tomar cualquier objeto y formato de él. –

5

comprobar éste, es compatible con el formateo:

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

Modo de empleo:

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) 
+0

No considera escaping: '' '' StringFormat ("{{key}}", nuevo Dictionary () {["key"] = "value"}); '' '' falla. –

7

Es posible ahora

Con Interpolated Strings de C# 6.0 se puede hacer esto:

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

Esto no es lo que se solicita. Si no sabe cómo se llama el campo, no puede tener una variable con ese identificador listo. – Moberg

+0

Puede hacer '$" Hola {d ["nombre"]} "que debe coincidir con lo que estaba pidiendo el OP – Juan

-1

Aquí es una buena solución que es muy útil cuando el formato de mensajes de correo electrónico: http://www.c-sharpcorner.com/UploadFile/e4ff85/string-replacement-with-named-string-placeholders/

Editado:

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

Ejemplo de uso:

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

Puesto que C# 6 liberada que son capaces de utilizar String Interpolation feature

Código que resuelve tu pregunta:

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