Geo*_*uer 8 .net string string.format
我认为这个问题的直接答案是"不",但我希望有人写了一个真正的简单库来做这件事(或者我可以做到......呃...)
让我用一个例子展示我正在寻找的东西.假设我有以下内容:
class Person {
string Name {get; set;}
int NumberOfCats {get; set;}
DateTime TimeTheyWillDie {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我希望能够做到这样的事情:
static void Main() {
var p1 = new Person() {Name="John", NumberOfCats=0, TimeTheyWillDie=DateTime.Today};
var p2 = new Person() {Name="Mary", NumberOfCats=50, TimeTheyWIllDie=DateTime.Max};
var str = String.Format(
"{0:Name} has {0:NumberOfCats} cats and {1:Name} has {1:NumberOfCats} cats. They will die {0:TimeTheyWillDie} and {1:TimeTheyWillDie} respectively
", p1, p2);
Console.WriteLine(str);
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道是否有这样的格式,或者有人写了一个库来做这件事?我知道它不应该太难,但我宁愿不重新实现轮子.
编辑:您不必为每个对象实现IFormattable ......这将是一个PITA,严重限制,以及相当大的维护负担.只需使用Reflection和IFormatProvider与ICustomFormatter,它将适用于任何对象.String.Format有一个重载,可以将一个参数作为参数.
我以前从未想过这个,但你引起了我的兴趣 - 所以我不得不快速旋转一下.请注意,我选择允许将其他格式字符串传递给属性值,并且它仅适用于非索引和可访问的属性(尽管您可以轻松添加它).
public class ReflectionFormatProvider : IFormatProvider, ICustomFormatter {
public object GetFormat(Type formatType) {
return formatType == typeof(ICustomFormatter) ? this : null;
}
public string Format(string format, object arg, IFormatProvider formatProvider) {
string[] formats = (format ?? string.Empty).Split(new char[] { ':' }, 2);
string propertyName = formats[0].TrimEnd('}');
string suffix = formats[0].Substring(propertyName.Length);
string propertyFormat = formats.Length > 1 ? formats[1] : null;
PropertyInfo pi = arg.GetType().GetProperty(propertyName);
if (pi == null || pi.GetGetMethod() == null) {
// Pass thru
return (arg is IFormattable) ?
((IFormattable)arg).ToString(format, formatProvider)
: arg.ToString();
}
object value = pi.GetGetMethod().Invoke(arg, null);
return (propertyFormat == null) ?
(value ?? string.Empty).ToString() + suffix
: string.Format("{0:" + propertyFormat + "}", value);
}
}
Run Code Online (Sandbox Code Playgroud)
你稍微修改过的例子:
var p1 = new Person() {Name="John", NumberOfCats=0, TimeTheyWillDie=DateTime.Today};
var p2 = new Person() {Name="Mary", NumberOfCats=50, TimeTheyWillDie=DateTime.MaxValue};
var str = string.Format(
new ReflectionFormatProvider(),
@"{0:Name} has {0:NumberOfCats} cats and {1:Name} has {1:NumberOfCats} cats.
They will die {0:TimeTheyWillDie:MM/dd/yyyy} and {1:TimeTheyWillDie} respectively.
This is a currency: {2:c2}.",
p1,
p2,
8.50M
);
Console.WriteLine(str);
Run Code Online (Sandbox Code Playgroud)
输出:
John has 0 cats and Mary has 50 cats.
They will die 12/10/2008 and 12/31/9999 11:59:59 PM respectively.
This is a currency: $8.50.
Run Code Online (Sandbox Code Playgroud)
“:”后面的内容作为参数传递给类的 ToString 方法。
只需声明一个接受字符串的 ToString 方法,“Name”、“NumberOfCats”等将在该参数中传递。
编辑:您必须实现 System.IFormattable。这有效:
class Person : IFormattable
{
public override string ToString()
{
return "Person";
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == "Name")
{
return "John";
}
if (format == "NumberOfCats")
{
return "12";
}
return "Unknown format string";
}
}
class Program
{
static void Main(string[] args)
{
Person p = new Person();
Console.WriteLine(string.Format("Name = {0:Name}",p));
Console.WriteLine(string.Format("NumberOfCats = {0:NumberOfCats}", p));
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2264 次 |
最近记录: |