Reputation: 42453
Is there a way to String.Format
a message without having to specify {1}, {2},
etc? Is it possible to have some form of auto-increment? (Similar to plain old printf
)
Upvotes: 6
Views: 16515
Reputation: 150
If someone is interested, I have modified Ashkan's solution to be able to run it under WinRT:
/// <summary>
/// Formats the log entry.
/// /// Taken from:
/// http://stackoverflow.com/questions/561125/can-i-pass-parameters-to-string-format-without-specifying-numbers
/// and adapted to WINRT
/// </summary>
/// <param name="format">The format.</param>
/// <param name="args">The arguments.</param>
/// <returns></returns>
/// <exception cref="System.FormatException">The string format is not valid</exception>
public static string FormatLogEntry(string format, object args)
{
Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");
MatchCollection m = r.Matches(format);
var properties = args.GetType().GetTypeInfo().DeclaredProperties;
foreach (Match item in m)
{
try
{
string propertyName = item.Groups[1].Value;
format = format.Replace(item.Value, properties.Where(p=>p.Name.Equals(propertyName))
.FirstOrDefault().GetValue(args).ToString());
}
catch
{
throw new FormatException("The string format is not valid");
}
}
return format;
}
Upvotes: 0
Reputation: 3222
I think the best way would be passing the property names instead of Numbers. use this Method:
using System.Text.RegularExpressions;
using System.ComponentModel;
public static string StringWithParameter(string format, object args)
{
Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");
MatchCollection m = r.Matches(format);
var properties = TypeDescriptor.GetProperties(args);
foreach (Match item in m)
{
try
{
string propertyName = item.Groups[1].Value;
format = format.Replace(item.Value, properties[propertyName].GetValue(args).ToString());
}
catch
{
throw new FormatException("The string format is not valid");
}
}
return format;
}
Imagine you have a Student Class with properties like: Name, LastName, BirthDateYear and use it like:
Student S = new Student("Peter", "Griffin", 1960);
string str = StringWithParameter("{Name} {LastName} Born in {BithDate} Passed 4th grade", S);
and you'll get: Peter Griffin born in 1960 passed 4th grade.
Upvotes: 2
Reputation: 71
I came up with this, again it's a bit cumbersome but it works fine for what I needed to do which was to pass a variable number or arguments to my own function in the same way as I'd use WriteLine. I hope it helps somebody
protected void execute(String sql, params object[] args)
{
for (int i = 0; i < args.Count(); i++ )
{
sql = sql.Replace(String.Format("{{{0}}}", i), args[i].ToString());
}
//...
}
Upvotes: 0
Reputation: 42453
One could always use this (untested) method, but I feel it's over complex:
public static string Format(char splitChar, string format,
params object[] args)
{
string splitStr = splitChar.ToString();
StringBuilder str = new StringBuilder(format + args.Length * 2);
for (int i = 0; i < str.Length; ++i)
{
if (str[i] == splitChar)
{
string index = "{" + i + "}";
str.Replace(splitStr, index, i, 1);
i += index.Length - 1;
}
}
return String.Format(str.ToString(), args);
}
Upvotes: 0
Reputation: 25628
You can use a named string formatting solution, which may solve your problems.
Upvotes: 6
Reputation: 71945
Afraid not -- where would it put the objects into the string? Using printf, you still need to put specifiers in somewhere.
Upvotes: 2