Después de pensar en esto, me di cuenta de lo que realmente deseaba, era que String.Format() tomaría un IDictionary como argumento, y que las plantillas podrían escribirse usando nombres en lugar de índices.
Para sustituciones de cadenas con muchas claves/valores posibles, los números de índice resultan en plantillas de cadena ilegibles, y en algunos casos, es posible que ni siquiera sepa qué elementos van a tener qué número, así que se me ocurrió lo siguiente extensión:
https://gist.github.com/896724
Básicamente esto le permite utilizar las plantillas de cuerda con los nombres en lugar de números, y un diccionario en lugar de una matriz, y le permite tener todas las otras buenas características de cadena.Format(), que permite el uso de un IFormatProvider personalizado, si es necesario, y permite el uso de toda la sintaxis de formateo habitual: precisión, longitud, etc.
El example proporcionado en el material de referencia para String.Format es un gran ejemplo de cómo las plantillas con muchos elementos numerados vuelven completamente ilegible - portar ese ejemplo para usar este nuevo método de extensión, se obtiene algo como esto:
var replacements = new Dictionary<String, object>()
{
{ "date1", new DateTime(2009, 7, 1) },
{ "hiTime", new TimeSpan(14, 17, 32) },
{ "hiTemp", 62.1m },
{ "loTime", new TimeSpan(3, 16, 10) },
{ "loTemp", 54.8m }
};
var template =
"Temperature on {date1:d}:\n{hiTime,11}: {hiTemp} degrees (hi)\n{loTime,11}: {loTemp} degrees (lo)";
var result = template.Subtitute(replacements);
como alguien ha señalado, si lo que estás escribiendo necesita estar muy optimizado, no use algo como esto: si tiene que formatear millones de cadenas de esta manera, en un bucle, la sobrecarga de memoria y rendimiento podría ser significativa.
Por otro lado, si le preocupa escribir código legible y mantenible, y si está haciendo, por ejemplo, un conjunto de operaciones de base de datos, en el gran esquema de cosas, esta función no agregará ningún gastos generales.
...
Para mayor comodidad, Yo intento de añadir un método que acepta un objeto anónimo en lugar de un diccionario:
public static String Substitute(this String template, object obj)
{
return Substitute(
template,
obj.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(obj, null))
);
}
Por alguna razón, esto no funciona - que pasa un objeto anónimo como new { name: "value" }
a ese método de extensión da un mensaje de error en tiempo de compilación diciendo que la mejor coincidencia fue la versión IDictionary de ese método. No estoy seguro de cómo solucionar eso. (¿alguien?)
+1 por hacer las cosas de la manera más simple :) –
(Aunque te refieres a Reemplazar (patrón, "Mike")) –
@Jon: Gracias. ¿Por qué usar un compilador cuando tienes un Jon? ;-) –