ver - programa en c#
Cómo proporcionar un marcador de posición de cadena personalizado para el formato de cadena (8)
Aquí hay otra versión de esto que encontré aquí: http://www.reddit.com/r/programming/comments/bodml/beef_up_params_in_c_5_to_solve_lambda_abuse/c0nrsf1
Cualquier solución a esto implicará una reflexión, que no es la ideal, pero aquí está su código con algunos de los otros problemas importantes de rendimiento resueltos. (No hay comprobación de errores. Agrégalo si quieres.):
1) Utiliza la reflexión directa en tiempo de ejecución, sin sobrecarga de DataBinder
2) No usa expresiones regulares, usa un estado y un análisis de un solo pase.
3) No convierte la cadena en una cadena intermedia y luego la convierte nuevamente al formato final.
4) Asigna y concatena con un único StringBuilder en lugar de agregar cadenas por todas partes y concatenarlas en nuevas cadenas.
5) Elimina la sobrecarga de la pila de llamar a un delegado para realizar operaciones de reemplazo.
6) En general, es un paso único que se escalará de una manera relativamente lineal (todavía hay un costo para cada búsqueda de propiedades y búsqueda de propiedades anidadas, pero eso es todo).
public static string FormatWith(this string format, object source)
{
StringBuilder sbResult = new StringBuilder(format.Length);
StringBuilder sbCurrentTerm = new StringBuilder();
char[] formatChars = format.ToCharArray();
bool inTerm = false;
object currentPropValue = source;
for (int i = 0; i < format.Length; i++)
{
if (formatChars[i] == ''{'')
inTerm = true;
else if (formatChars[i] == ''}'')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
sbResult.Append((string)(pi.PropertyType.GetMethod("ToString", new Type[]{}).Invoke(pi.GetValue(currentPropValue, null), null)));
sbCurrentTerm.Clear();
inTerm = false;
currentPropValue = source;
}
else if (inTerm)
{
if (formatChars[i] == ''.'')
{
PropertyInfo pi = currentPropValue.GetType().GetProperty(sbCurrentTerm.ToString());
currentPropValue = pi.GetValue(source, null);
sbCurrentTerm.Clear();
}
else
sbCurrentTerm.Append(formatChars[i]);
}
else
sbResult.Append(formatChars[i]);
}
return sbResult.ToString();
}
Tengo una cuerda
string str ="Enter {0} patient name";
Estoy usando string.format para formatearlo.
String.Format(str, "Hello");
Ahora, si quiero que el paciente también se recupere de alguna configuración, entonces necesito cambiar la cadena a algo como "Enter {0} {1} name"
. Entonces reemplazará el {1} con el segundo valor. El problema es que quiero, en lugar de {1}, algún otro formato, como {pat}
. Pero cuando intento usarlo, arroja un error. La razón por la que quiero un formato diferente es que hay muchos archivos que necesito cambiar así (que pueden contener {0}, {1} etc.). Así que necesito un marcador de posición personalizado que se pueda reemplazar en tiempo de ejecución.
Es posible que desee revisar FormatWith 2.0 por James Newton-King . Le permite usar nombres de propiedades como tokens de formato como este:
var user = new User()
{
Name = "Olle Wobbla",
Age = 25
};
Console.WriteLine("Your name is {Name} and your age is {Age}".FormatWith(user));
También puedes usarlo con tipos anónimos.
ACTUALIZACIÓN: También hay una solution similar por Scott Hanselman, pero se implementa como un conjunto de métodos de extensión en Object
lugar de String
.
ACTUALIZACIÓN 2012 : Puede obtener NETFx String.FormatWith Extension Method NuGet de Calrius Consulting en NuGet.org
ACTUALIZACIÓN 2014 : También hay StringFormat.NET y StringFormat.NET littlebit
Probablemente esté mejor usando Reemplazar para el campo personalizado y Formato para el resto, como:
string str = "Enter {0} {pat} name";
String.Format(str.Replace("{pat}", "Patient"), "Hello");
Quería algo que funcionara más como el formato de cadena de Python, así que escribí esto: https://gist.github.com/samwyse/b225b32ae1aea6fb27ad9c966b9ca90b
Úsalo así:
Dim template = New FormatFromDictionary("{cat} vs {dog}")
Dim d = New Dictionary(Of String, Object) From {
{"cat", "Felix"}, {"dog", "Rex"}}
Console.WriteLine(template.Replace(d)) '' Felix vs Rex
También puede usar el ejemplo de Marc Gravell y Extender el objeto de clase String:
public static class StringExtension
{
static readonly Regex re = new Regex(@"/{([^/}]+)/}", RegexOptions.Compiled);
public static string FormatPlaceholder(this string str, Dictionary<string, string> fields)
{
if (fields == null)
return str;
return re.Replace(str, delegate(Match match)
{
return fields[match.Groups[1].Value];
});
}
}
Ejemplo de uso:
String str = "I bought a {color} car";
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("color", "blue");
str.FormatPlaceholder(fields));
Vi todas las respuestas anteriores, sin embargo, no pude responder correctamente la pregunta :)
¿Hay alguna razón en particular por la que el siguiente código no cumpla con su requisito?
string myFirstStr = GetMyFirstStrFromSomewhere();
string mySecondStr = GetMySecondStrFromSomewhere();
string result = "Enter " + myFirstStr + " " + mySecondStr + " name";
Regex
con un MatchEvaluator
parece una buena opción:
static readonly Regex re = new Regex(@"/{([^/}]+)/}", RegexOptions.Compiled);
static void Main()
{
string input = "this {foo} is now {bar}.";
StringDictionary fields = new StringDictionary();
fields.Add("foo", "code");
fields.Add("bar", "working");
string output = re.Replace(input, delegate (Match match) {
return fields[match.Groups[1].Value];
});
Console.WriteLine(output); // "this code is now working."
}
object[] myInts = new int[] {8,9};
Sin embargo puedes salirte con:
object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);