对于C#,是否有相当于Java的ToStringBuilder?什么是好的C#版本功能?

时间:2010-03-10 14:33:13

标签: c# java reflection apache-commons tostring

在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}"
  • 可以使用System.Reflection.Emit来预编译ToString委托。

还有其他想法吗?

更新

只是为了澄清ToStringBuilder是一个与StringBuilder不同的生物。我正在寻找类似于Apache Common的ToStringBuilder功能的东西,它具有诸如多行格式化,不同样式和反射基础ToString创建等功能。感谢。

更新2

我已经建立了自己的。请参阅here

8 个答案:

答案 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)

查看此项目......

http://commonsdotnet.codeplex.com/

答案 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的例子更灵活。