开发者

Is there an equivalent to Java's ToStringBuilder for C#? What would a good C# version feature?

开发者 https://www.devze.com 2022-12-22 07:01 出处:网络
In the Java world we have Apache Commons\' ToStringBuilder to help with creating toString() implementations.

In the Java world we have Apache Commons' ToStringBuilder to help with creating toString() implementations.

Does anyone know of a decent free implementation for C#? Are there better alternatives I don't know about?

If no free implementation exists than I guess this question becomes more of a question of "What would make a good ToStringBuilder in C# 3?"

Off the top of my head:

  • It could offer both reflection and manual ToString string creation.

  • It would be really cool if it could make use of Expression trees.

Something like this..

 public override string ToString()
   {
      return new ToStringBuilder<Foo>(this)
         .Append(t => t.Id)
         .Append(t => t.Name)
         .ToString();
   }

Which would return:

 "Foo{Id: 1, Name: AName}"
  • It could use System.Reflection.Emit to precompile a ToString delegate.

Any othe开发者_如何学Gor ideas?

UPDATE

Just to clarify ToStringBuilder is a different creature to StringBuilder.. I'm looking for something akin to the functionality of Apache Common's ToStringBuilder, it has features such as multi-line formatting, different styles and reflection base ToString creation. Thanks.

UPDATE 2

I've built my own. See here.


EDIT: OK, you want to use reflection so you don't have to type property names. I think this will get you what you're after:

// 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() + "}";
    }
}

Example:

// 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();
}

Behold, the behavior you're after:

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());
}

Output:

Thing{Id: 10, Name: "Bob"}


The original question concerned C# 3.5 but since then I've upgraded to C# 4.

I thought I'd share my new version here in case it's of benefit to others. It has all of the features mentioned in this thread and compiles at runtime to a fast Stringify method.

Get it here: ToStringBuilder


It might not be exactly what you are after since it is not free, but Resharper will do this. It is a fantastic plugin to visual studio that does a lot more than generate ToString. But it will do that to. put your cursor inside your class, hit alt+insert and choose formating members.


Use .NET's StringBuilder.

Note that you'll have to provide a little template yourself.

E.g:

public StringBuilder ToStringBuilder<T>(T type) where T : IYourInterface
{
StringBuilder sb = new StringBuilder();
sb.append(type.key);
// more appends

return sb;
}

Provided a kinda generic way here. You'll be able to create your own neat solution with the System.Reflection namespace in .NET

Cheers


See this project...

http://commonsdotnet.codeplex.com/


ObjectPrinter will do this for you with a number of customizable features. documentation is still a little rough, but we've been using it in production for years with great results.


I think that you are on to something with using Expressions. I read this article just the other night: Getting Information About Objects, Types, and Members with Expression Trees

I bet that you could combine those techniques with the code that Dan posted on this thread to get what you are after.


I don't know of any existing projects that would do what you want, but it wouldn't be that hard to implement the example you gave using lambdas.

Here's another [untested/uncompiled/possibly faulty] idea using anonymous delegates:

public override string ToString() {
    return this.ToString(x => {
        x.Append(t => t.Id);
        x.Append(t => t.Name);
    });
}

This ToString() overload would be written as an extension method, so you get a reference to the source object, and would accept an Action<T> where [T] is the type of source object. The ToString() method would then new up a string builder or internal object of some sort, execute the anonymous method passed in from the caller, and then wrap the result in any opening/closing text that is necessary.

To be clear, I haven't actually tried this. I just think its a little more flexible than the lambda-based example in the original question.

0

精彩评论

暂无评论...
验证码 换一张
取 消