I have:
public static string Format(this string text, params object[] args)
{
return string.Format(text, args);
}
So I can do:
"blablabla {0}".Format(variable1);
Is it a good/bad? Can it become even shorter? I want to have strings build seamlessly, like writing the text without worrying before or after of parameters and stuff:
// bad
return "date: " + DateTime.Now.ToString("dd.MM.yyyy") + "\ntime: " + DateTime.Now.ToString("mm:HH:ss") + "\nuser: " + _user + " (" + _status + ")";
// better, but you have to deal with order of {0}...{n} and order of parameters
return string.Format("date: {0}\ntime: {1}\user: {2} ({3})", ...);
// ideal
return "date: {DateTime.Now{dd:MM:yyyy}}\ntime: {...}\nuser: {_user} ({_status})";
It's doesn't quite match your ideal, but something like this might work for you:
public static class Extensions
{
public static string Format(this object data, string format)
{
var values = new List<object>();
var type = data.GetType();
format = Regex.Replace(format, @"(^|[^{])\{([^{}]+)\}([^}]|$)", x =>
{
var keyValues = Regex.Split(x.Groups[2].Value,
"^([^:]+):?(.*)$")
.Where(y => !string.IsNullOrEmpty(y));
var key = keyValues.ElementAt(0);
var valueFormat = keyValues.Count() > 1 ?
":" + keyValues.ElementAt(1) :
string.Empty;
var value = GetValue(key, data, type);
values.Add(value);
return string.Format("{0}{{{1}{2}}}{3}",
x.Groups[1].Value,
values.Count - 1,
valueFormat,
x.Groups[3].Value);
});
return string.Format(format, values.ToArray());
}
private static object GetValue(string name, object data, Type type)
{
var info = type.GetProperty(name);
return info.GetValue(data, new object[0]);
}
}
This should allow you to do this sort of formatting on any object:
new {Person = "Me", Location = "On holiday"}
.Format("{Person} is currently {Location}");
It will also allow you to add some formatting:
new {Person = "Me", Until = new DateTime(2013,8,1)}
.Format("{Person} is away until {Until:yyyy-MM-dd});
How is this for you? I'm sure the code could be improved in terms of efficiency but it works!
Well, one bad thing there is that by only having a single params object[]
method you force an extra array allocation per-call.
You may notice that string.Format
has a range of overloads for taking low numbers of arguments (these are very commonly used) - I would suggest duplicating them.
Your "ideal" scenario could be done by re-writing the string.Format
method, but you'd need to pass in the values, i.e.
return "date: {date}\ntime: {...}\nuser: {_user} ({_status})"
.Format(new { date = DateTime.Now, _user, _status });
(and using your own custom Format
method, or one like this) - but note this forces a new object instance per call.
Actually, at one point the mono compiler had an experimental flag to enable this directly. I don't know if it is maintained.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With