如何自动将类的所有属性及其值以字符串形式显示?

46

想象一个有很多公共属性的类。由于某些原因,无法将该类重构为更小的子类。

我想添加一个ToString重写,返回类似以下内容:

属性1:属性1的值\n
属性2:属性2的值\n
...

有没有办法做到这一点?

5个回答

110

我认为你可以在这里使用一些反射。看一下Type.GetProperties()

public override string ToString()
{
    return GetType().GetProperties()
        .Select(info => (info.Name, Value: info.GetValue(this, null) ?? "(null)"))
        .Aggregate(
            new StringBuilder(),
            (sb, pair) => sb.AppendLine($"{pair.Name}: {pair.Value}"),
            sb => sb.ToString());
}

3
+1 很好的回答。有一个小缺陷。在if语句中,_PropertyInfos总是为空,应该改为_PropertyInfos = this.GetType().GetProperties(); - Conrad Frix
3
@AlexRice:是的,你说得对。我想,每个遇到这个问题的人都会自己解决。但是有一个复制粘贴的解决方案,也考虑到了这一点,可以让每个人都更容易解决。所以我改变了代码来处理空值。 - Oliver
1
你为什么要用下划线和大写字母来命名变量?比如_PropertyInfos?这似乎违反了所有编码规范。 - Kellen Stuart
1
惯例的好处在于它们既不是规则也不是法律,而且有很多种。 - Oliver
2
这里只是一个更新,你实际上不需要缓存propertyinfo。它已经被运行时内部缓存了RuntimeTypeCache。当你第二次访问它时,它会很便宜。 - joe
显示剩余2条评论

38

@Oliver的答案是扩展方法(我认为很适合它)

public static string PropertyList(this object obj)
{
  var props = obj.GetType().GetProperties();
  var sb = new StringBuilder();
  foreach (var p in props)
  {
    sb.AppendLine(p.Name + ": " + p.GetValue(obj, null));
  }
  return sb.ToString();
}

1
相同的简短格式:public static string AsString(this object convertMe) => string.Join("\n",convertMe.GetType().GetProperties().Select(prop => $"{prop.Name}: {prop.GetValue(convertMe, null)}")); - tire0011

4
您可以通过反射来实现这一点。
PropertyInfo[] properties = MyClass.GetType().GetProperties();
foreach(PropertyInfo prop in properties)
{
...
}

MyClass.GetType() 不会起作用。你应该在 MyClass 的实例上调用 GetType()。 - Andrew Bezzub
或使用 typeof(MyClass)。 - VikciaR

2
你可以从StatePrinter包的状态详细 introspection 中获取灵感,这里是类内省器。请注意保留 html 标签。

1
如果您可以访问所需类的代码,则可以重写 ToString() 方法。如果不能,则可以使用 Reflections 从 Type 对象中读取信息:
typeof(YourClass).GetProperties()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接