在Java世界中,我们使用Apache Commons'ToStringBuilder来帮助创建toString()实现。
有没有人知道C#的免费实现?有没有更好的替代品我不知道?
如果没有自由实现,我想这个问题更像是一个问题“什么会在C#3中成为一个好的ToStringBuilder?”
脱离我的头顶:
它可以提供反射和手动ToString字符串创建。
如果可以使用表达式树,真的很酷。
像这样......
public override string ToString()
{
return new ToStringBuilder<Foo>(this)
.Append(t => t.Id)
.Append(t => t.Name)
.ToString();
}
哪会回来:
"Foo{Id: 1, Name: AName}"
还有其他想法吗?
更新
只是为了澄清ToStringBuilder是一个与StringBuilder不同的生物。我正在寻找类似于Apache Common的ToStringBuilder功能的东西,它具有诸如多行格式化,不同样式和反射基础ToString创建等功能。感谢。
更新2
我已经建立了自己的。请参阅here。
答案 0 :(得分:13)
编辑:好的,您想要使用反射,因此您不必键入属性名称。我想这会让你得到你想要的东西:
// forgive the mangled code; I hate horizontal scrolling
public sealed class ToStringBuilder<T> {
private T _obj;
private Type _objType;
private StringBuilder _innerSb;
public ToStringBuilder(T obj) {
_obj = obj;
_objType = obj.GetType();
_innerSb = new StringBuilder();
}
public ToStringBuilder<T> Append<TProperty>
(Expression<Func<T, TProperty>> expression) {
string propertyName;
if (!TryGetPropertyName(expression, out propertyName))
throw new ArgumentException(
"Expression must be a simple property expression."
);
Func<T, TProperty> func = expression.Compile();
if (_innerSb.Length < 1)
_innerSb.Append(
propertyName + ": " + func(_obj).ToString()
);
else
_innerSb.Append(
", " + propertyName + ": " + func(_obj).ToString()
);
return this;
}
private static bool TryGetPropertyName<TProperty>
(Expression<Func<T, TProperty>> expression, out string propertyName) {
propertyName = default(string);
var propertyExpression = expression.Body as MemberExpression;
if (propertyExpression == null)
return false;
propertyName = propertyExpression.Member.Name;
return true;
}
public override string ToString() {
return _objType.Name + "{" + _innerSb.ToString() + "}";
}
}
示例:
// from within some class with an Id and Name property
public override string ToString() {
return new ToStringBuilder<SomeClass>(this)
.Append(x => x.Id)
.Append(x => x.Name)
.ToString();
}
看哪,你所追求的行为:
class Thing {
public int Id { get; set; }
public string Name { get; set; }
public override string ToString() {
return new ToStringBuilder<Thing>(this)
.Append(t => t.Id)
.Append(t => t.Name)
.ToString()
}
}
void Main() {
var t = new Thing { Id = 10, Name = "Bob" };
Console.WriteLine(t.ToString());
}
输出:
事情{Id:10,姓名:“Bob”}
答案 1 :(得分:4)
最初的问题涉及C#3.5,但从那时起我已升级到C#4。
我想我会在这里分享我的新版本,以防它对别人有益。它具有此线程中提到的所有功能,并在运行时编译为快速Stringify方法。
在此处获取:ToStringBuilder
答案 2 :(得分:3)
它可能不完全是你所追求的,因为它不是免费的,但Resharper会这样做。它是视觉工作室的一个很棒的插件,它比生成ToString做了很多。但它会这样做。把光标放在你的类中,点击alt + insert并选择格式化成员。
答案 3 :(得分:1)
使用.NET的StringBuilder。
请注意,您必须自己提供一个小模板。
例如:
public StringBuilder ToStringBuilder<T>(T type) where T : IYourInterface
{
StringBuilder sb = new StringBuilder();
sb.append(type.key);
// more appends
return sb;
}
在这里提供了一种generic
方式。
您将能够使用.NET中的System.Reflection
命名空间创建自己的整洁解决方案
干杯
答案 4 :(得分:1)
查看此项目......
答案 5 :(得分:1)
ObjectPrinter会为您提供许多可自定义的功能。文档仍然有点粗略,但我们已经在生产中使用它多年,效果很好。
答案 6 :(得分:0)
我认为您正在使用表达式。我刚才读了这篇文章:Getting Information About Objects, Types, and Members with Expression Trees
我敢打赌,你可以将这些技术与Dan在这个帖子上发布的代码结合起来,以获得你想要的东西。
答案 7 :(得分:0)
我不知道任何现有项目会做你想做的事情,但实现你使用lambdas给出的例子并不难。
这是使用匿名代表的另一个[未经测试/未编译/可能有缺陷]的想法:
public override string ToString() {
return this.ToString(x => {
x.Append(t => t.Id);
x.Append(t => t.Name);
});
}
此ToString()
重载将被写为扩展方法,因此您将获得对源对象的引用,并接受Action<T>
,其中[T]是源对象的类型。然后,ToString()方法将新建一个字符串构建器或某种内部对象,执行从调用者传入的匿名方法,然后将结果包装在任何必要的打开/关闭文本中。
要清楚,我实际上并没有尝试这个。我认为它比原始问题中基于lambda的例子更灵活。